Laravel Tutorials

Laravel Fake Assertions Now Accept Property Arrays

Published
Laravel Fake Assertions Now Accept Property Arrays image

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

Jack Bayliss contributed the change in #61770.

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Sponsored

serpapi logo
SerpApi

The Web Search API for Your LLM and AI Applications

Visit SerpApi

The latest

View all →
Route::query() and Model defaults() in Laravel 13.35 image

Route::query() and Model defaults() in Laravel 13.35

Read article
Laravel AI SDK 1.1 Adds Agent Skills and Cohere Chat image

Laravel AI SDK 1.1 Adds Agent Skills and Cohere Chat

Read article
VMPal: Give Your AI Agent a Whole Computer image

VMPal: Give Your AI Agent a Whole Computer

Read article
Synapse: A Dev Dashboard for Laravel AI SDK Agents image

Synapse: A Dev Dashboard for Laravel AI SDK Agents

Read article
Decide with Jev: Three Questions in One Request with the Laravel AI SDK image

Decide with Jev: Three Questions in One Request with the Laravel AI SDK

Read article
Grant: Enum-Based Roles and Permissions for Laravel image

Grant: Enum-Based Roles and Permissions for Laravel

Read article