我正在开发一个 Laravel 应用程序。我正在对我的应用程序进行单元测试。现在我在测试验证过程时遇到了麻烦。
我现在想做的是注册一个用户,然后测试是否发送了验证电子邮件,然后我将获得该注册的验证链接,然后我将对该链接执行一些操作。
这是我的测试
public function test_user_can_be_verified_and_redirected_based_on_role()
{
Notification::fake();
$user = $this->registerUser();
Notification::assertSentTo($user, SendEmailVerificationNotification::class);
}
protected function registerUser()
{
$user = factory(User::class)->make();
$this->post(route('register'), [
'name' => $user->name,
'email' => $user->email,
'password' => 'testing',
'password_confirmation' => 'testing',
])->assertRedirect();
return User::whereEmail($user->email)->first();
}
但问题是,即使我从浏览器注册时发送了通知,也没有发送通知。我也喜欢检索验证链接并做一些事情。我怎样才能做到这一点?
不是一个完美的解决方案,但它确实有效,如果有人以某种方式破坏了这个功能,我会知道的。 :)
首先覆盖
verificationUri
通知的受保护方法VerifyEmail
并公开
class EmailVerificationNotification extends VerifyEmail
{
public function verificationUrl($notifiable) {
return parent::verificationUrl($notifiable);
}
}
然后用它生成一个链接并对其进行断言..
/** @test */
public function an_user_can_verify_his_email_address()
{
$notification = new EmailVerificationNotification();
$user = factory(User::class)->create(['email_verified_at' => null]);
$uri = $notification->verificationUrl($user);
$this->assertSame(null, $user->email_verified_at);
$this->actingAs($user)->get($uri);
$this->assertNotNull($user->email_verified_at);
}
只需运行以下命令即可在VerifyEmail通知之外轻松生成验证URL:
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)]
);
无需公开
verificationUrl()
方法。
这是我的解决方案:
public function testVerifyEmailValidatesUser(): void
{
// VerifyEmail extends Illuminate\Auth\Notifications\VerifyEmail in this example
$notification = new VerifyEmail();
$user = factory(User::class)->create();
// New user should not has verified their email yet
$this->assertFalse($user->hasVerifiedEmail());
$mail = $notification->toMail($user);
$uri = $mail->actionUrl;
// Simulate clicking on the validation link
$this->actingAs($user)
->get($uri);
// User should have verified their email
$this->assertTrue(User::find($user->id)->hasVerifiedEmail());
}
@florent 的答案很棒,但是对于 Laravel 5.7.29,我发现使用工厂创建的新用户自动设置了 email_verified_at 标志,因此第一个测试 - 用户尚未验证 - 失败。
添加两行后,观察到正确的操作:
public function testVerifyEmailValidatesUser(): void
{
// VerifyEmail extends Illuminate\Auth\Notifications\VerifyEmail in this example
$notification = new VerifyEmail();
$user = factory(User::class)->create();
$user->email_verified_at = null; // Needs to be set manually
$user->save(); // Commit the change to the record
// New user should not has verified their email yet
$this->assertFalse($user->hasVerifiedEmail());
$mail = $notification->toMail($user);
$uri = $mail->actionUrl;
// Simulate clicking on the validation link
$this->actingAs($user)
->get($uri);
// User should have verified their email
$this->assertTrue(User::find($user->id)->hasVerifiedEmail());
}```