DEV Community

MacDonald Chika
MacDonald Chika

Posted on

How To Test Mail and Database Notifications in Laravel 8

I was working on a project in Laravel and needed to test the mail content of a mail notification and also the database notification but I could not figure it out. After some research, I figured that you can actually unit test or assert mail notification content as well as database notification without sending an actual notification. I will show you how to do that in this article.

If you are reading this, I will assume that you already know how to write unit tests in Laravel using PHPUnit. If you don't , you can click here to get you started.

Firstly, we will create a notification using this Laravel command
php artisan make:notification TestNotification

Your file should look like this.


namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class TestNotification extends Notification
{
    use Queueable;

    private $user;

    public function __construct($user)
    {
        $this->$user = $user;
    }

    public function via($notifiable)
    {
        return ['mail','database'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', url('/'))
                    ->line('Thank you for using our application!');
    }

    public function toArray($notifiable)
    {
        return [
            'some' => 'data'
        ];
    }
}

Enter fullscreen mode Exit fullscreen mode

And then in your test, you should fake the notification by calling the notification facade and then a static function fake().

We are going to test the database notification. In your test file, create a function testDatabaseNotification(). Afterward, we will arrange our test case, act and assert.

public function testDatabaseNotification()
    {   
        // Arrange
        Notification::fake(); 
        $this->user = User::factory()->create();
        $email_subject = "Test Notification";

        // Act 
        $this->user->notify(new TestNotification($email_subject));

        // Assert
        Notification::assertSentTo($this->user, TestNotification::class, function ($notification, $channels) use($email_subject){
            $this->assertContains('database', $channels);

            $databaseNotification = (object)$notification->toArray($this->user);
            $this->assertEquals( $email_subject, $databaseNotification->title);

            return true;
        });
    }
Enter fullscreen mode Exit fullscreen mode

Now we are going to test our mail notification

public function testMailNotification()
    {   
        // Arrange
        Notification::fake();
        $this->user = User::factory()->create();
        $email_subject = "Test notification";

        // Act
        $this->user->notify(new TestNotification($email_subject));

        // Assert
        Notification::assertSentTo($this->user, TestNotification::class, function ($notification, $channels) use($email_subject){
            $this->assertContains('mail', $channels);

            $mailNotification = (object)$notification->toMail($this->user);
            $this->assertEquals($email_subject, $mailNotification->subject,);

            $this->assertEquals('The introduction to the notification.', $mailNotification->introLines[0]);
            $this->assertEquals('Thank you for using our application!', $mailNotification->outroLines[0]);
            $this->assertEquals('Notification Action', $mailNotification->actionText);
            $this->assertEquals($mailNotification->actionUrl, url('/'));

            return true;
        });
}
Enter fullscreen mode Exit fullscreen mode

You see here that we are retrieving the content of the mail notification.

Here is the full code

<?php

namespace Tests\Unit;

use App\Notifications\TestNotification;
use Illuminate\Support\Facades\Notification;
use App\Model\User;
use Tests\TestCase;

class MailNotificationTest extends TestCase
{
    /**
     * @var \Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|mixed
     */
    private $user;

    /**
     * A basic test example.
     *
     * @return void
     */
    public function testDatabaseNotification()
    {
        Notification::fake();
        $this->user = User::factory()->create();
        $email_subject = "Test Notification";

        $this->user->notify(new TestNotification($email_subject));

        Notification::assertSentTo($this->user, TestNotification::class, function ($notification, $channels) use($email_subject){
            $this->assertContains('database', $channels);

            $databaseNotification = (object)$notification->toArray($this->user);
            $this->assertEquals( $email_subject, $databaseNotification->title);

            return true;
        });
    }

    public function testMailNotification()
    {
        Notification::fake();
        $this->user = User::factory()->create();
        $email_subject = "Test notification";

        $this->user->notify(new TestNotification($email_subject));

        Notification::assertSentTo($this->user, TestNotification::class, function ($notification, $channels) use($email_subject){
            $this->assertContains('mail', $channels);

            $mailNotification = (object)$notification->toMail($this->user);
            $this->assertEquals($email_subject, $mailNotification->subject,);

            $this->assertEquals('The introduction to the notification.', $mailNotification->introLines[0]);
            $this->assertEquals('Thank you for using our application!', $mailNotification->outroLines[0]);
            $this->assertEquals('Notification Action', $mailNotification->actionText);
            $this->assertEquals($mailNotification->actionUrl, url('/'));

            return true;
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

Now we have successfully asserted mail and database content in Laravel notification.
Please share in the comment below what you think about this.

Happy Coding :)

Discussion (0)