Interview frequency: …
Short answer
Fakes replace real execution with a recorder, letting you verify after the code runs that the job, event, or message was dispatched with the right data without actually running it.
Explanation
After Queue::fake(), jobs are recorded instead of executed. Check them with assertPushed, assertNotPushed, or assertPushedOn and a callback that inspects job properties. Likewise, use Event::fake() with assertDispatched and Mail::fake() with assertSent or assertQueued, depending on whether a message is sent immediately or queued. Test the job itself separately by calling handle() directly so fakes do not hide errors inside the job. To fake only certain events, pass their names to Event::fake([...]) so other Eloquent events continue to work normally.
Code example
public function test_placing_an_order_dispatches_payment_and_sends_confirmation(): void
{
Queue::fake();
Mail::fake();
Event::fake([OrderPlaced::class]); // other events (e.g. Eloquent) still run
$this->postJson('/api/orders', ['sku' => 'tea', 'qty' => 2])->assertCreated();
Queue::assertPushed(ProcessPayment::class, fn ($job) => $job->order->qty === 2);
Queue::assertNotPushed(RefundPayment::class);
Mail::assertQueued(OrderConfirmation::class);
Event::assertDispatched(OrderPlaced::class);
}
// The job itself gets its own test that calls handle() directly
public function test_payment_job_marks_order_paid(): void
{
$order = Order::factory()->create();
(new ProcessPayment($order))->handle(app(PaymentGateway::class));
$this->assertTrue($order->fresh()->isPaid());
}Common mistakes
- Calling Event::fake() without selecting events, disabling Eloquent model events (such as creating) and causing unexpected test failures.
- Checking only that a job was dispatched without testing its logic, leaving handle() errors undetected.