首页 文章

单元测试Laravel密码重置电子邮件 - mailable没有排队

提问于
浏览
2

我正在使用Laravel附带的auth . 我正在测试您放入电子邮件的页面,当您点击提交按钮时,密码重置电子邮件将发送到您的电子邮件 .

我手动执行密码重置电子邮件 . 但我创建了此测试以确保密码重置电子邮件已发送但它无法正常工作 .

有1次失败:1)预期的[Illuminate \ Foundation \ Auth \ ResetPassword] mailable没有排队 . 声明false为真的失败 .

我遵循以下代码:

https://github.com/JeffreyWay/council/blob/master/tests/Feature/Auth/RegisterUserTest.php

<?php

namespace Tests\Controllers\Unit;

use Tests\TestCase;
use Illuminate\Support\Facades\Mail;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ResetPasswordEmailTest extends TestCase
{

    use RefreshDatabase;


    public function setUp()
    {
        parent::setUp();

        Mail::fake();
    }


    /** @test */
    public function does_send_password_reset_email()
    {
        $user = factory('App\User')->create();

        $this->post(route('password.email'), ['email' => $user->email])

        Mail::assertQueued(ResetPassword::class);
    }

}

2 回答

  • 0

    您收到该错误,因为密码重置电子邮件是 Notification 而不是 Mailable . 请注意,您还必须保存假用户,以便密码重置代码可以在数据库中查找它 . 对我有用的是这样的:

    <?php
    
    namespace Tests\Controllers\Unit;
    
    use Tests\TestCase;
    use Illuminate\Support\Facades\Notification;
    use Illuminate\Auth\Notifications\ResetPassword;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    
    class ResetPasswordEmailTest extends TestCase
    {
        use RefreshDatabase;
    
        public function setUp()
        {
            parent::setUp();
            Notification::fake();
        }
    
        /** @test */
        public function does_send_password_reset_email()
        {
            $user = factory('App\User')->create();
            $user->save();
            $this->post(route('password.email'), ['email' => $user->email])
            Notification::assertSentTo($user, ResetPassword::class);
        }
    }
    

    您还可以使用以下内容检查电子邮件的内容:

    Notification::assertSentTo(
        $user,
        ResetPassword::class, 
        function($notification, $channels) use ($user) {
            $mail = $notification->toMail($user)->build();
            $expected_subject = "Here's your password reset";
            return $mail->subject === $expected_sub;
        }
    );
    
  • -1

    您可以通过控制器执行此操作 . 这是一个例子:

    public function postforgotpassword(Request $request){
        $this->validate($request, ['phone' => 'required']);
    
        $user=User::where('phone',$request->get('phone'))->first();
        if($user['email']==""){
            return Redirect()->back()->with('status', 'You dont have email assigned. Contact admin for reset');
        }
    
        $response = Password::sendResetLink($request->only('phone'), function (Message $message) {
            $message->subject($this->getEmailSubject());
        });
    
        switch ($response) {
            case Password::RESET_LINK_SENT:
            return redirect()->back()->with('status', trans($response));
    
            case Password::INVALID_USER:
            return redirect()->back()->withErrors(['phone' => trans($response)]);
        }
    }
    
    protected function getEmailSubject(){
        return isset($this->subject) ? $this->subject : 'Your Password Reset Link';
    }
    

    它会将带有令牌的链接发送到您的电子邮件中 . 然后,当您想使用该链接时,您可以尝试这样做:

    public function getreset($token = null){
        if (is_null($token)) {
            throw new NotFoundHttpException;
        }
    
        return view('auth.reset')->with('token', $token);
    }
    
    public function postreset(Request $request){
        $this->validate($request, [
            'token' => 'required',
            'phone' => 'required',
            'password' => 'required|confirmed',
        ]);
    
        $credentials = $request->only(
            'phone', 'password', 'password_confirmation', 'token'
        );
    
    
        $response = Password::reset($credentials, function ($user, $password) {
            $this->resetPassword($user, $password);
        });
    
        switch ($response) {
            case Password::PASSWORD_RESET:
            return redirect($this->redirectPath());
    
            default:
            return redirect()->back()
            ->withInput($request->only('phone'))
            ->withErrors(['phone' => trans($response)]);
        }
    }
    protected function resetPassword($user, $password){
        $user->password = bcrypt($password);
        $user->save();
        Auth::login($user);
    }
    

    路线应该是:

    Route::post('forgotpassword', array('as' => 'forgotpassword.post', 'uses' => 'YourController@postforgotpassword'));
    
    Route::get('password/reset/{token}', array('as' => 'password.reset', 'uses' => 'YourController@getreset'));
    Route::post('password/reset', array('as' => 'password.reset.post', 'uses' => 'YourController@postreset'));
    

    希望这有帮助,祝你有个美好的一天 .

相关问题