Things to remember
- When you call event::fake(), no event listeners will be executed.
- You can assert only the events that faked not actually running events.
- Event faking method of Laravel can fake all events, selected events or all events except selected ones.
- You can check dispatched events are listened by correct event listener.
Event Faking options
Assert event is dispatched
Event::assertDispatched(YourEventClass::class);
Assert same event dispatched multiple times
//Same Event is dispatched twice
Event::assertDispatched(YourEventClass::class, 2);
Assert event is listened by correct event listener
Event::assertListening(
YourEventClass::class,
EventListenerClass::class
);
Fake only selected event or events
Event::fake([
YourEventClassOne::class,
YourEventClassTwo::class,
]);
Fake all events
Event::fake();
Fake all events except selected events
Event::fake()->except([
YourEventClass::class,
]);
Check event is not dispatched
Event::assertNotDispatched(YourEventClass::class);
Check any event is not dispatched or fired.
Event::assertNothingDispatched();
Fake event only for a portion of your test. Image you want to fake event inside a code block without affecting other part of the code. Rest of the code also has event and need to run event listeners to pass the test correctly.
$result = Event::fakeFor(function () {
//execute your code (request, factory, service, etc.) that will fire the event
Event::assertDispatched(YourEventClass::class);
//Return anything you want to continue the test.
//Remove return if nothing to return
return true;
});
Preparing a sample project with events to test
Lets setup our Laravel project and create sample events and event listeners to test.
Step 1: Setup your Laravel Project.
Step 2: Create two event classes as ItemShipped and OrderPlaced.
php artisan make:event ItemShipped
php artisan make:event OrderPlaced
Step 3: Create two event listener classes for above events
For ItemShipped event
php artisan make:listener NotifyShippingManager
For OrderPlaced event
php artisan make:listener NotifyOwner
Step 4: Bind event listeners to listen on events
NotifyShippingManager listener should listen for ItemShipped event. (Just type hint the event in handle method.)
namespace App\Listeners;
use App\Events\ItemShipped;
use Illuminate\Support\Facades\Log;
class NotifyShippingManager
{
/**
* Handle the event.
*/
public function handle(ItemShipped $event): void
{
Log::info("Handle method of event Listener running..");
}
}
NotifyOwner listener should listen for OrderPlaced event. (Just type hint the event in handle method.)
namespace App\Listeners;
use App\Events\OrderPlaced;
use Illuminate\Support\Facades\Log;
class NotifyOwner
{
/**
* Handle the event.
*/
public function handle(OrderPlaced $event): void
{
Log::info('Handle method of Notify Owner');
}
}
Step 5: Dispatch ItemShipped event when application received a get request to root domain.
use App\Events\ItemShipped;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
Log::info('Dispatch event');
ItemShipped::dispatch();
});
Testing Events using PHP Unit Testing
Below shows list of use cases for testing events. First create the test file using below artisan command. Follow naming convention like below example. Make sure to end the name of your test file name with “Test”.
php artisan make:test ItemShippedTest
Now use below artisan command to test above created test file using PHP unit testing.
php artisan test --filter=ItemShippedTest
Case 1: Test event is dispatched
Dispatch single event when application received the get request on root domain.
Route::get('/', function () {
Log::info('Dispatch event');
ItemShipped::dispatch();
});
Modify test file to check whether event is fired. Make sure to run this test using the artisan command given above.
namespace Tests\Feature;
use App\Events\ItemShipped;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ItemShippedTest extends TestCase
{
/**
* A basic feature test example.
*/
public function test_example(): void
{
Event::fake();
$this->get('/');
Event::assertDispatched(ItemShipped::class);
}
}
Case 2: Test same event dispatched 2 times
Modify web.php file to dispatch same event twice.
Route::get('/', function () {
Log::info('Dispatch events');
ItemShipped::dispatch();
ItemShipped::dispatch();
});
Testing whether same event fired twice.
namespace Tests\Feature;
use App\Events\ItemShipped;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ItemShippedTest extends TestCase
{
/**
* A basic feature test example.
*/
public function test_example(): void
{
Event::fake();
$this->get('/');
Event::assertDispatched(ItemShipped::class, 2);
}
}
Case 3: Test event is not dispatched
You can use assertNotDispatched to check whether OrderPlaced event is not dispatched since it was not declared in the web.php file
namespace Tests\Feature;
use App\Events\ItemShipped;
use App\Events\OrderPlaced;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ItemShippedTest extends TestCase
{
/**
* A basic feature test example.
*/
public function test_example(): void
{
Event::fake();
$this->get('/');
Event::assertDispatched(ItemShipped::class);
Event::assertNotDispatched(OrderPlaced::class);
}
}
Case 4: Use two events and make sure to one event executed without faking and second event executed using event faking.
Execute both event classes from web.php
<?php
use App\Events\ItemShipped;
use App\Events\OrderPlaced;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
Log::info('Dispatch events');
ItemShipped::dispatch();
OrderPlaced::dispatch();
});
You cannot assert OrderPlaced event since that event was not faked. Only faked events can be asserted.
<?php
namespace Tests\Feature;
use App\Events\ItemShipped;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ItemShippedTest extends TestCase
{
/**
* A basic feature test example.
*/
public function test_example(): void
{
Event::fake(ItemShipped::class);
$this->get('/');
Event::assertDispatched(ItemShipped::class);
}
}