Last month, I shared a testing tip on the benefits of making multiple separate assertions inside a closure instead of chaining them together.
Today I want to highlight one time you can't do this.
Let's say the code you're testing issues two events of the same type, but with different data.
Because it's being issued more than once, you can't use the closure approach I mentioned before to test both events.
Here's the approach I would use in this scenario:
Event::assertDispatchedTimes(OrderShipped::class, 2);
Event::assertDispatched(OrderShipped::class, function (OrderShipped $event) use ($user1) {
$eventCustomer = getProperty($event, 'customer');
return $eventCustomer->is($user1);
});
Event::assertDispatched(OrderShipped::class, function (OrderShipped $event) use ($user2) {
$eventCustomer = getProperty($event, 'customer');
return $eventCustomer->is($user2);
});
Because we're only using the return value to make our assertion, Laravel helpfully keeps track of both closures and makes sure they each pass at least once.
I still prefer the technique using specific independent assertions from the original tip, but when you're testing multiple instances of the same event (or mail, notification, job, etc), this is a great alternative.
Here to help,
Joel
P.S. If you appreciate these daily tips, you can support us by purchasing one of our Laravel books. You'll help us out and learn something in the process.