Checkout calls an exchange-rate API, queues a SendInvoice job and emails a receipt, and a test must really do none of them. Each facade's fake() puts a recorder with assertions in the container in place of the real service, so the test checks what the code meant to send:
Http::preventStrayRequests(); // any URL that is not faked throws
Http::fake(['rates.example.com/*' => Http::response(['rates' => ['MYR' => 4.2]])]);
Queue::fake();
Mail::fake();
$user = User::factory()->create();
$book = Product::factory()->create(['price' => 10, 'stock' => 5]);
$this->actingAs($user)
->postJson('/checkout', ['product_id' => $book->id, 'qty' => 2])
->assertOk()
->assertExactJson(['total_usd' => 20, 'total_myr' => 84]);
Http::assertSent(fn ($request) => $request['base'] === 'USD');
Queue::assertPushed(SendInvoice::class, fn ($job) => $job->total === 20.0);
Mail::assertSent(ReceiptMail::class, fn ($mail) => $mail->hasTo($user->email));
$this->assertSame(3, $book->fresh()->stock);Output
PASS Tests\Feature\CheckoutTest ✓ checkout converts queues and mails 0.17s ✓ a product stops being new after a week 0.01s
The second test calls $this->travel(8)->days() between two isNew() checks. travelTo() and freezeTime() also move the clock that now() reads, and the clock resets after each test. Event, Notification and Storage have fakes too. For your own classes, $this->mock() binds a Mockery 10,724 double into the container (Mockery and Hand-Written Fakes).