在触发通知或执行触发通知的操作后,如何测试电子邮件是否作为最终结果发送?
理想情况下,有一个通知仅用于发送电子邮件。我首先想到的是触发它,然后检查是否发送了Mail::assertSent()
。但是,这似乎不起作用,因为Notification会返回Mailable,但不会调用Mail::send()
。
相关GitHub问题:https://github.com/laravel/framework/issues/27848
我测试的第一种方法:
/** @test */
public function notification_should_send_email()
{
Mail::fake();
Mail::assertNothingSent();
// trigger notification
Notification::route('mail', 'email@example.com')
->notify(new SendEmailNotification());
Mail::assertSent(FakeMailable::class);
}
Notification toMail()方法的外观如下:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\FakeMailable
*/
public function toMail($notifiable)
{
return (new FakeMailable())
->to($notifiable->routes['mail']);
}
设置示例可用https://github.com/flexchar/laravel_mail_testing_issue
答案 0 :(得分:1)
您可以使用mailCatcher然后扩展您的TestCase
class MailCatcherTestCase extends TestCase
{
protected $mailCatcher;
/**
* MailCatcherTestCase constructor.
* @param $mailCatcher
*/
public function __construct($name = null, array $data = [], $dataName = ''
) {
parent::__construct($name, $data, $dataName);
$this->mailCatcher = new Client(['base_uri' => "http://127.0.0.1:1080"]);
}
protected function removeAllEmails() {
$this->mailCatcher->delete('/messages');
}
protected function getLastEmail() {
$emails = $this->getAllEmail();
$emails[count($emails) - 1];
$emailId = $emails[count($emails) - 1]['id'];
return $this->mailCatcher->get("/messages/{$emailId}.json");
}
protected function assertEmailWasSentTo($recipient, $email) {
$recipients = json_decode(((string)$email->getBody()),
true)['recipients'];
$this->assertContains("<{$recipient}>", $recipients);
}
}
然后您就可以在测试中使用
/** @test */
public function notification_should_send_email()
{
// trigger notification
Notification::route('mail', 'email@example.com')
->notify(new SendEmailNotification());
$email = $this->getLastEmail();
$this->assertEmailWasSentTo($email, 'email@example.com');
}
因为您可以提取邮件,所以可以测试邮件正文,主题,抄送,附件等。
别忘了删除tearDown中的所有邮件
希望这会有所帮助。