What's the secret of testing a mailable was sent from a notification?
Testing the notification:
it('does send notification when model is deleted', function() {
Notification::fake();
$this->model->delete();
Notification::assertSentTo($this->model->user, MyModelDeletedNotification::class);
});
Passes.
Testing the mailable:
it('does send email when model is deleted', function() {
Mail::fake();
$this->model->delete();
Mail::assertQueued(MyModelDeletedMail::class, 1);
});
Fails. No mails queued.
When a model is deleted a observer method is triggered:
public function deleted(MyModel $model)
{
if ($model->isForceDeleting()) {
return;
}
$model->user->notify(new MyModelDeletedNotification($model));
}
Notification:
class MyModelDeleted extends Notification implements ShouldQueue
{
use Queueable;
...
public function via($notifiable)
{
return ['mail', 'database'];
}
public function toMail($notifiable)
{
return (new MyModelDeletedMail($this->model))->to($notifiable->email);
}
...
}
Mailable:
class ConsultationDeleted extends Mailable
{
use Queueable, SerializesModels;
...
public function build()
{
...
}
}
When I dump("foobar") inside the mailables constructor or build method, the message is appearing in the log. However the test fails. What am I missing here?
Regarding using Mail:fake in the context of notifications:
It is not a very good way to test because it catches only mails sent using the Mail facade (doesn't intercept mails sent through a notification or using a mailer retrieved via dependency injection).
Make sure you have set
<server name="MAIL_MAILER" value="array"/>
phpunit.xml. In your test:
it('does send email', function() {
// business logic
$emails = app()->make('mailer')->getSwiftMailer()->getTransport()->messages();
assertCount(1, $emails);
assertEquals([$this->user->email], array_keys($emails[0]->getTo()));
});
This worked for me using laravel 8.