【问题标题】:Laravel Reset Password Notification does not get dispatched in test but does send an emailLaravel 重置密码通知不会在测试中发送,但会发送电子邮件
【发布时间】:2021-02-20 19:57:45
【问题描述】:

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

诚挚的问候,谢谢!

【问题讨论】:

  • 在测试开始时放置期望值。如果通知已经发送,它就不能期待通知。
  • 对不起,我不明白你想说什么。你能改写一下吗? @MHewison
  • 你的测试没有问题,结构完全正确。仔细检查您的代码。也许您不发送通知并触发发送重置电子邮件的事件。您还可以在测试期间使用 dd() 调试您的步骤,以了解当前正在运行的步骤。

标签: php laravel events notifications mocking


【解决方案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 并确定@987654329 @失败。

TLDR 确保 config/auth.php (param providers.users.model) 和 UserFactory.php 依赖相同的模型。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 对不起,我确实得到了与我的测试完全相同的错误!
    • 对不起,删除 Notification::fake();我已经编辑以反映
    • 不,不适合我。我得到完全相同的错误The following expected notification were not dispatched: [Illuminate\Auth\Notifications\ResetPassword]
    • 所以在这种情况下,很可能没有发送 ResetPassword 通知。
    猜你喜欢
    • 2017-08-02
    • 1970-01-01
    • 2018-07-04
    • 1970-01-01
    • 2016-03-01
    • 1970-01-01
    • 2013-12-18
    • 2015-08-13
    • 1970-01-01
    相关资源
    最近更新 更多