Checking which job was pushed, or which event or notification was sent, usually means writing a callback that compares each property. Starting in Laravel 13.35, the Queue, Bus, Event, and Notification fakes accept an array of expected property values in place of that callback.
#Before and After
Take a test for a podcast upload that pushes a ProcessPodcast job. Before 13.35, checking the job's properties took a callback:
Queue::fake();
$this->actingAs($user)->post('/podcasts', $data);
Queue::assertPushed(ProcessPodcast::class, function (ProcessPodcast $job) use ($podcast, $user) {
return $job->podcast->is($podcast)
&& $job->user->is($user)
&& $job->status === 'pending';
});
With 13.35, the expected values go in an array:
Queue::assertPushed(ProcessPodcast::class, [
'podcast' => $podcast,
'user' => $user,
'status' => 'pending',
]);
The other fakes work the same way:
Event::assertDispatched(OrderShipped::class, ['order' => $order]);
Bus::assertDispatched(GenerateInvoice::class, ['order' => $order]);
Notification::assertSentTo($user, InvoicePaid::class, ['invoice' => $invoice]);
The array also works with the negative and variant assertions that take a callback, such as assertNotPushed(), assertPushedOn(), assertNotDispatched(), and assertNotSentTo():
Queue::assertNotPushed(ProcessPodcast::class, ['user' => $otherUser]);
Pass the class name as the first argument. The array cannot be used with the form of assertPushed() that takes only a typed closure.
#How Values Are Compared
Every key in the array has to match for the assertion to pass. Each value is compared with strict equality (===), with one exception: when the expected and actual values are both Eloquent models, they are compared with $model->is(), which checks the primary key, table, and connection.
Strict equality has consequences for other objects. Two Carbon instances for the same moment are different objects, so 'scheduled_at' => now() fails. Use a callback when you need to compare dates, value objects, or collections:
Queue::assertPushed(SendReminder::class, function (SendReminder $job) use ($user) {
return $job->user->is($user)
&& $job->sendAt->equalTo(now()->addDay());
});
The array checks top-level properties only, so it has no dot notation for nested values.
#Public Properties Only
The fake reads each property from outside the object, so the properties have to be public. A job that keeps its data in protected properties, or behind getter methods, still needs a callback. Constructor property promotion with public works:
class ProcessPodcast implements ShouldQueue
{
use Queueable;
public function __construct(
public Podcast $podcast,
public User $user,
public string $status = 'pending',
) {}
}
A key that does not exist on the object fails the assertion instead of throwing an error, so a typo in a property name shows up as a failed test.
#Further Reading
- Route::query() and Model defaults() in Laravel 13.35
- Watch Jason McCreary's "Testing With Fakes" talk from Laracon
- Learn how to start Testing in Laravel with Simple Examples using PHPUnit and PEST
Jack Bayliss contributed the change in #61770.
Комментарии (0)
Пока нет комментариев — будьте первым.