我正在为我的 Laravel 项目编写测试。现在我正在测试登录、注销、重置密码等身份验证代码。
遗憾的是,我的测试失败了,因为没有发送通知。我嘲笑了通知,但
assertSendTo
总是失败,原因是The expected [Illuminate\Auth\Notifications\ResetPassword] notification was not sent.
。
但是,当实际请求重置密码电子邮件时(不是在测试中,作为我网站上的普通用户),我确实收到了重置密码电子邮件。所以,它是功能性的并且可以工作,但在我的测试中不是这样。怎么会这样?
.evn
也是正确的,我已经将我的邮件主机设置为mailtrap.io
并且我也收到了这封电子邮件...这是我能给你的最好证明。
这是我的测试:
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;
use Tests\TestCase;
class AuthTest extends TestCase
{
/** @test */
public function a_not_logged_in_user_can_request_a_new_password()
{
Notification::fake();
$email = Str::random() . "@gmail.com";
$current_password = Str::random(16);
$current_password_hash = Hash::make($current_password);
$user = User::factory()->create([
'email' => $email,
'password' => $current_password_hash
]);
$response = $this->json('POST', route('password.email'), ['email' => $email]);
$response->assertStatus(200);
$response->assertLocation(route('home'));
//$this->expectsNotification($user, ResetPassword::class);
Notification::assertSentTo($user, ResetPassword::class);
}
}
有什么想法为什么测试不起作用或者有什么问题吗? 同样非常奇怪的是,响应代码
200
表明一切都成功,没有任何问题。
这是我使用
assertSentTo
执行测试时遇到的错误
1) Tests\Feature\Auth\LoggedIn\ForgotPassword\AuthTest::a_not_logged_in_user_can_request_a_new_password
The expected [Illuminate\Auth\Notifications\ResetPassword] notification was not sent.
Failed asserting that false is true.
MyWebsiteProject/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php:68
/MyWebsiteProject/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:261
MyWebsiteProject/tests/Feature/Auth/LoggedIn/ForgotPassword/AuthTest.php:35
这是我使用
expectsNotification
执行它时遇到的错误
1) Tests\Feature\Auth\LoggedIn\ForgotPassword\AuthTest::a_logged_in_user_can_request_a_new_password
The following expected notification were not dispatched: [Illuminate\Auth\Notifications\ResetPassword]
MyWebsiteProject/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MocksApplicationServices.php:281
MyWebsiteProject/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:237
MyWebsiteProject/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:153
亲切的问候和谢谢!
我的应用程序最初是在 L5 中创建的,当时默认的
User.php
完全限定类名是
App\User.php
但是,根据L8新模式,我将其复制(以避免重构......我的错)到App\Models\User.php
。
https://twitter.com/taylorotwell/status/1296556354593792000
这种部分的错位,虽然,留下了我的一些测试,特别是那些涉及虚假通知的测试,其中
UserFactory
不断调度(通过NotificationFake.php
)到App\User.php
而不是App\Models\User.php
,并确定assertSentTo
到失败。
TLDR 确保
config/auth.php
(参数 providers.users.model
)和 UserFactory.php
依赖于相同的模型。
期望只是“期望某事将会发生”,在你的情况下,你是在事后期待它。后者是断言的用例。您需要的是类似以下内容。
class AuthTest extends TestCase
{
/** @test */
public function a_not_logged_in_user_can_request_a_new_password()
{
$email = Str::random() . "@gmail.com";
$current_password = Str::random(16);
$current_password_hash = Hash::make($current_password);
$user = User::factory()->create([
'email' => $email,
'password' => $current_password_hash
]);
// Expect that something is going to happen
$this->expectsNotification($user, ResetPassword::class);
$response = $this->json('POST', route('password.email'), ['email' => $email]);
// Assertion that something has happened
$response->assertStatus(200);
$response->assertLocation(route('home'));
}
}
如果上述解决方案都不适合您(就像我的情况一样),请尝试在测试函数的顶部添加此行;
$this->withoutExceptionHandling();
这将为您提供一个很好的错误消息,说明问题可能来自何处。就我而言,我使用了错误的路线。
我在定制认证系统时也遇到了同样的问题。我创建了一个自定义通知并使用它代替 Illuminate\Auth\Notifications\ResetPassword;这对我有用。
如果您在
User
模型中使用自定义通知类覆盖 sendPasswordResetNotification
,请确保在测试文件中替换
Notification::assertSentTo($user, ResetPassword::class);
与
Notification::assertSentTo($user, YOUR_CUSTOM_CLASS::class);