I am using the base PHPUnit config file with the default TestCase.php file.
I am seeking a way to check if an event is fired multiple times during a test. Current code looks like:
function test_fires_multiple_events()
{
$this->expectsEvents(SomeEvent::class);
}
Ideally, I would want:
function test_fires_multiple_events()
{
$this->expectsEvents(SomeEvent::class)->times(3);
}
After walking through the code in MocksApplicationServices
, I was able to piggyback the trait, and the fields it captures when the withoutEvents()
method.
The extension would look like:
function test_fires_multiple_events()
{
$this->withoutEvents(); // From MocksApplicationServices
$c = collect($this->firedEvents)
->groupBy(function($item, $key) { return get_class($item); })
->map(function($item, $key) { return $item->count(); });
$this->assertsEqual(3, $c->get(SomeEvent::class));
}
To step through what collection is doing:
1) collect($this->firedEvents)
: Takes the captured events and stores them in a collection. It's important to note, that MocksApplicationServices
pushes each event into an array, meaning it is already keeping count.
2) groupBy(function($item, $key) { return get_class($item); })
: Groups by the class name, meaning we have a collection of arrays now.
3) map(function($item, $key) { .. }
: Simply tally up the children.
This results in a structure like:
Illuminate\Support\Collection (1) (
protected items -> array (2) [
'App\Events\SomeEvent' => integer 2
'App\Events\SomeOtherEvent' => integer 1
]
)
Edit Just to clean it up a bit - you could add the following to your base test case file:
public function assertEventFiredTimes($event, $count)
{
$this->assertEquals(
count(collect($this->firedEvents)
->groupBy(function($item, $key) { return get_class($item); })
->get($event, [])),
$count
);
}
And then in your tests:
$this->assertEventFiredTimes(SomeEvent::class, 3);
Not forgetting to add withoutEvents()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With