Laravel 8 Notification Unit Testing not working: The expected notification was not sent
Hi community,
Context:
- Laravel 8.83.18
- PHPUnit 9.5.21
- PHP 8.1.7
I'm trying to implement (it's my first time) a Unit Test for a use case that sends an email as a Laravel Notification. I am implementing my web app with a Domain-Driven Design approach and, to simplify and debug, I've checked Laravel Official Documentation (laravel com/docs/8.x/mocking#notification-fake), and I am trying to make the simplest case work, but it doesn't (without using my DDD approach that sends the notification through a use case). I will show you my code: Test Class:
<?php
declare(strict_types=1);
namespace Tests\Unit\Modules\Test;
use App\Models\User\User;
use App\Notifications\TestNotification;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped()
{
Notification::fake();
$emil = '[email protected]';
$user = new User();
$user->setAttribute('email', $emil);
// Executing notification sending...
Notification::route('mail', $email)->notify(new TestNotification($user));
// Assert a notification was sent to the given users...
Notification::assertSentTo(
[$user], TestNotification::class
);
}
}
Test Notification class:
<?php
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'
];
}
}
Error Response:
The expected [App\Notifications\TestNotification] notification was not sent.
Failed asserting that false is true.
/opt/project/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php:83
/opt/project/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php:67
/opt/project/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:261
/opt/project/tests/Unit/Modules/Test/ExampleTest.php:27
Of course, if I try to send the notification out of the Unit Test, it works. I'm using this and I receive the email in my Mailhog container.
Route::get('/test-notification', function (){
Notification::route('mail', '[email protected]')->notify(new TestNotification(new \App\Models\User\User()));
return 'Notification Sent';
});
So my question is, why the notification is not sent inside Unit Test, because my call it's the same, it does not match with Laravel says in their DOC.
In addition, I wonder if instead of using an instance of a Laravel model the user class, I can use another kind of object, even a Mock, I guess so, as long as I use the Trait "Notifiable". Correct?
Thank you very much
Please or to participate in this conversation.