LaravelPHP单元测试。微笑测试,但有一个失败

LaravelPHP单元测试。微笑测试,但有一个失败,laravel,laravel-5,Laravel,Laravel 5,这两项测试用于密码重置。我用的是从Laravel的盒子里出来的基本认证。第一次测试失败了。第二个测试通过了。他们非常相似。我不明白为什么第一次考试不及格 在第一次测试中: 我正在创建一个用户 获取密码重置令牌 使用正确的数据发出更改密码的post请求 它一直告诉我我的电子邮件有错误。我不明白为什么 <?php namespace Tests\Controllers\Unit; use Tests\TestCase; use Illuminate\Support\Facades\DB;

这两项测试用于密码重置。我用的是从Laravel的盒子里出来的基本认证。第一次测试失败了。第二个测试通过了。他们非常相似。我不明白为什么第一次考试不及格

在第一次测试中:

  • 我正在创建一个用户
  • 获取密码重置令牌
  • 使用正确的数据发出更改密码的post请求
  • 它一直告诉我我的电子邮件有错误。我不明白为什么

    <?php
    
    namespace Tests\Controllers\Unit;
    
    use Tests\TestCase;
    use Illuminate\Support\Facades\DB;
    use Illuminate\Support\Facades\Hash;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    
    class ResetPasswordTest extends TestCase
    {
    
        use RefreshDatabase;
    
    
        // This test is currently failing. It's saying I have error with email.
    
        public function test_does_change_a_users_password()
        {
            // Create user 
            $user = factory('App\User')->create();
    
            // This post route creates a new password reset token and stores it into the database.
            $this->post(route('password.email'), ['email' => $user->email]);
    
            // I get the token
            $token = DB::table('password_resets')->whereEmail($user->email)->first()->token;
    
            $this->from(route('password.reset', $token));
    
            // Change password with the correct data
            $response = $this->post('password/reset', [
                'token'                 => $token,
                'email'                 => $user->email,
                'password'              => 'password',
                'password_confirmation' => 'password'
            ]);
    
            // This is true... It tells me I have an error with my email.
            $reponse->assertSessionHasErrors('email');
    
            // This is false. The password is not changed to the new password.
            $this->assertTrue(Hash::check('password', $user->fresh()->password));
        }
    
    
        // This test is the working one.
    
        public function test_does_change_a_users_password2()
        {
            $user = factory('App\User')->create();
    
            $token = Password::createToken($user);
            $new_password = 'bestpassword99';
    
            DB::table('password_resets')->insert([
                'token'   => $token,
                'email'   => $user->email,
            ]);
    
            $this->from(route('password.reset', $token));
    
            $response = $this->post('password/reset', [
                'token'                 => $token,
                'email'                 => $user->email,
                'password'              => $new_password,
                'password_confirmation' => $new_password
            ]);
    
    
            $this->assertTrue(Hash::check($new_password, $user->fresh()->password));
        }
    
    }  
    

    如果您使用
    dd($response)
    检查响应,您可以看到Laravel抱怨令牌无效

    但是为什么呢Laravel不在数据库中存储确切的令牌。它存储令牌的散列。这是为了确保获得数据库读取权限的用户不能(轻松)重置用户密码

    因此,与其从数据库中获取哈希值,不如获取发送给用户的令牌

    让我们尝试从通知中提取令牌:

    $bag = new \stdClass();
    
    Notification::assertSentTo($user, \Illuminate\Auth\Notifications\ResetPassword::class, function ($notification) use ($bag) {
        $bag->token = $notification->token;
        return true;
    });
    
    $token = $bag->token;
    
    并把它放在你的测试中:

    /** @test */
    public function does_change_a_users_password()
    {
        Notification::fake();
    
        // Create user
        $user = factory(User::class)->create();
    
        // This post route creates a new password reset token and stores it into the database.
        $this->post(route('password.email'), ['email' => $user->email]);
    
        // get the password reset token
        $bag = new \stdClass();
        Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($bag) {
            $bag->token = $notification->token;
            return true;
        });
        $token = $bag->token;
    
        $this->from(route('password.reset', $token));
    
        // Change password with the correct data
        $response = $this->post('password/reset', [
            'token'                 => urlencode($token),
            'email'                 => $user->email,
            'password'              => 'password',
            'password_confirmation' => 'password'
        ]);
    
        //$response->assertSessionHasErrors('password');
    
        // Ensure password is changed.
        $this->assertTrue(Hash::check('password', $user->fresh()->password));
    }
    

    您如何验证负责更新密码的方法?为什么您的第二个测试没有用
    @test
    注释?它是用@test注释的,这样您就不必将测试放在函数名中运行。不完全是主题,但这些是集成测试,决不是单元测试。如果您在这个测试中打开代码覆盖率,您将看到您几乎访问了整个核心Laravel框架。这不是单元测试的概念。单元测试是创建一个用户并检查它是否存在。@johnysiver你读了我写的东西了吗?仔细地喜欢。