Laravel: Как написать интеграционный тест для уведомлений, отправляющих электронную почту - PullRequest
1 голос
/ 14 марта 2019

Как проверить, что электронное письмо отправляется в качестве окончательного результата после запуска уведомления или выполнения действия, которое вызывает уведомление?

В идеале, уведомление просто для отправки электронного письма.Моей первой мыслью было запустить его, а затем проверить, отправлено ли Mail::assertSent().Однако, похоже, что это не работает, так как Notification возвращает Mailable, но не вызывает Mail::send().

Соответствующая проблема GitHub: https://github.com/laravel/framework/issues/27848

Мой первый подход для test :


    /** @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);
    }

, а метод уведомления 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

1 Ответ

1 голос
/ 14 марта 2019

Вы можете использовать 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

надеюсь, это поможет.

...