How do you test database notifications?

Published 2 weeks ago by pimski

Hi there,

How do you test database notifications? The following piece of code works when running in the browser, but gives no results when running in a test case:

auth()->user()->notify(new \App\Notifications\ExportFinished);
dd(\DB::table('notifications')->select()->get()); // empty result set in test

Is the test 'mocking' the notification? I'm not calling Notification::fake(); in my test!

martinbean

@pimski I think we’re going to need to see some more code.

pimski
pimski
2 weeks ago (36,570 XP)

Why? User is standard and the notification is generated with the artisan command "make:notification"

I did change the via method to:

public function via($notifiable)
    {
        return ['database'];
    }
Nash
Nash
1 week ago (65,670 XP)

You can mock the notification being sent:

use App\Notifications\ExportFinished;
use Illuminate\Support\Facades\Notification;

...

Notification::fake();

$user->notify(new ExportFinished);

Notification::assertSentTo($user, ExportFinished::class);

Should work just the same regardless of delivery method (email, database).

https://laravel.com/docs/5.6/mocking#notification-fake

pimski
pimski
1 week ago (36,570 XP)

Hi @Nash thanks for the reply. I already managed to test there 'is' a notification. However, my next step was to check the contents of the notification (as stored in the database). And this is what isn't working.

The posted code does work when I check it in the browser. So my guess there is some test-magic going on that prevents the notification from actually being saved in the database. How can one actually save notifications in the database in tests?

Nash
Nash
1 week ago (65,670 XP)

You can access the notification and check the contents:

Notification::assertSentTo(
    $user, 
    ExportFinished::class, 
    function ($notification, $channels) {
        dd($notification); // <-- this is your notification
    }
);
pimski
pimski
1 week ago (36,570 XP)

Aha. So the way to check a notification is by using the Notification facade? And not by checking the notifications relationship on the user? Even if you don't use Notification::fake() in your test...

Nash
Nash
1 week ago (65,670 XP)

Aha. So the way to check a notification is by using the Notification facade? And not by checking the notifications relationship on the user? Even if you don't use Notification::fake() in your test...

@pimski No, this is related to my previous example using Notification::fake(). I just pointed out that you can access the notification and check the contents just fine. You don't need to manually query the DB for that.

pimski
pimski
1 week ago (36,570 XP)

@Nash I understood that, and got my test working, so thanks for that! I was just wondering if code like this is never possible:

$user->notify(new MyDatabaseNotification());
$this->assertCount(1, $user->notifications);

To me this feels more natural. But maybe I just need to change my test-mindset

Nash
Nash
1 week ago (65,670 XP)

I haven't tried it your way so I can't really say. Maybe the notifications are going to your real db instead of your testing db?

Remember that notifications can also be sent by email, in which case you probably don't want them to be sent for real. Using Notification::fake() makes sure that doesn't happen in case you or someone else changes the delivery method later on.

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