Laravel 重置密码通知在测试中不会发送,但会发送电子邮件

问题描述 投票:0回答:5

我正在为我的 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

亲切的问候和谢谢!

php laravel events notifications mocking
5个回答
1
投票

我的应用程序最初是在 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
依赖于相同的模型。


0
投票

期望只是“期望某事将会发生”,在你的情况下,你是在事后期待它。后者是断言的用例。您需要的是类似以下内容。

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'));
    }
}

0
投票

如果上述解决方案都不适合您(就像我的情况一样),请尝试在测试函数的顶部添加此行;

$this->withoutExceptionHandling();

这将为您提供一个很好的错误消息,说明问题可能来自何处。就我而言,我使用了错误的路线。


0
投票

我在定制认证系统时也遇到了同样的问题。我创建了一个自定义通知并使用它代替 Illuminate\Auth\Notifications\ResetPassword;这对我有用。


0
投票

如果您在

User
模型中使用自定义通知类覆盖
sendPasswordResetNotification
,请确保在测试文件中替换

Notification::assertSentTo($user, ResetPassword::class);

Notification::assertSentTo($user, YOUR_CUSTOM_CLASS::class);
© www.soinside.com 2019 - 2024. All rights reserved.