Back to Course |
Testing in Laravel 11: Advanced Level

Testing Events and Listeners with Fake

Another non-standard or non-linear thing you can test in Laravel is the Event/Listener pattern.

By now, you should probably have noticed the pattern in how "faking" something in Laravel works:

  • You fake the process
  • You make other arrangements
  • You perform the main "act"
  • You assert the results

So, it is pretty similar with Events and Listeners.


The Example

When you use the Laravel Breeze starter kit, registration fires an Event that the user has registered. Then, someone can add a Listener or multiple Listeners to do something, like notify someone.

app/Http/Controllers/Auth/RegisteredUserController.php:

class RegisteredUserController extends Controller
{
// ...
 
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
 
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
 
event(new Registered($user));
 
Auth::login($user);
 
return redirect(route('dashboard', absolute: false));
}
}

The Test

First, let's write a post request to register a user.

use function Pest\Laravel\post;
 
test('registration fires event', function () {
post('/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
});

Let's fake the event using the Event facade and the fake() method.

use function Pest\Laravel\post;
use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Registered;
 
test('registration fires event', function () {
Event::fake();
 
post('/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
 
Event::assertDispatched(Registered::class);
});

That would test that the event was actually fired.

Important: It wouldn't test that the Listener was successfully executed, but it would at least test that it was dispatched.

But, if you want to check if the Event Listener is listening, you can use the assertListening() assertion.

use function Pest\Laravel\post;
use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
 
test('registration fires event', function () {
Event::fake();
 
post('/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
 
Event::assertDispatched(Registered::class);
Event::assertListening(Registered::class, SendEmailVerificationNotification::class);
});