How to test mail sent from Notification

Posted 3 months ago by bwrigley

My users can specify if they have Notifications sent to them instantly or to be notified daily of any pending Notifications.

This all works fine with manual testing, so now I'd like to write a feature test around this. This is what I have so far:

    public function test_instant_notification_is_sent(): void
    {
        Mail::fake();

        $this->user = $user = factory(User::class)->create();

        $this->user->update(
            [
                'notification_frequency' => 'instant',
                'notification_method' => 'email',
                'notification_email' => $this->email,
            ]
        );

        $this->user->save();

        $email = ['subject' => 'subject', 'data' => 'data'];
        $sms = 'Test Notification';
        $database = ['some' => 'data'];

        $this->user->notify(new TestNotification($email, $sms, $database));

        Mail::assertSent(MailMessage::class);

and I've written the TestNotification to go with it:

class TestNotification extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @param string[] $email
     * @param string $sms
     * @param string[] $database
     * @return void
     */
    public function __construct(array $email, string $sms, array $database)
    {
        $this->email = $email;
        $this->sms = $sms;
        $this->database = $database;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return string[]
     */
    public function via($notifiable): array
    {
        return [$notifiable->preferredNotificationMethod()];
    }

    /**
     * @param  mixed  $notifiable
     * @return string[]
     */
    public function toDatabase($notifiable): array
    {
        return $this->database;
    }

    /**
     * @param  mixed  $notifiable
     * @return string[]
     */
    public function toNexmo($notifiable): array
    {
        return (new NexmoMessage)
            ->content($this->sms);
    }

    /**
     * @param  mixed  $notifiable
     * @return string[]
     */
    public function toMail($notifiable): MailMessage
    {
        return (new MailMessage)
            ->greeting($this->email['subject'])
            ->line('Testing Notifications!')
            ->line('Thank you for using our application!');
    }
}

So my test fails because, as I now see, MailMessage is not a mailable and I think Mail::fake() and the mail assertions only work with mailables.

Incidentally, if I remove Mail::fake() the email is sent fine.

How have others managed to test this please without actually sending the email.

Please sign in or create an account to participate in this conversation.

Reply to

Use Markdown with GitHub-flavored code blocks.