laravelmastery
SnippetsArticlesSeriesNews

Test-driven Laravel · Lesson 3 of 3

Test-driven Laravel · Lesson 3

Faking storage and HTTP

Edges and judgementTesting

The queue test proved the job was pushed. A test that writes a PDF should not touch the disk you use in development. A test that calls a payment provider should not call the provider. Fake the disk and fake HTTP, and fail the test if the code calls a host you did not expect.

Video

01 Swap both edges before the request

Storage::fake() replaces the default disk. Http::fake() returns the response you describe. preventStrayRequests() makes any other host a failure.

PHP
it('stores the pdf after the provider accepts the charge', function () {
    Storage::fake();
    Http::preventStrayRequests();
    Http::fake([
        'payments.example/*' => Http::response(['id' => 'pay_1'], 200),
    ]);

    $invoice = Invoice::factory()->issued()->create();

    $this->actingAs($invoice->team->owner)
        ->post('/invoices/'.$invoice->id.'/charge')
        ->assertRedirect();

    Storage::assertExists('invoices/'.$invoice->id.'.pdf');
});

Assert the file path the feature promised. Asserting that some file exists is too weak: a bug that writes the wrong name would still pass.

Http::assertSent() is there when the interesting part is the request body, such as the amount. Use it in the test that is about the amount, not in this one.

02 Assert the amount when the amount is the point

The PDF test above only cares that a file landed after a 200. A charge test cares that the provider was asked for this invoice’s total. assertSent() receives the request. A wrong amount fails here, and a stray host still fails because preventStrayRequests() is on.

PHP
it('charges the invoice total', function () {
    Http::preventStrayRequests();
    Http::fake([
        'payments.example/*' => Http::response(['id' => 'pay_1'], 200),
    ]);

    $invoice = Invoice::factory()->issued()->create(['total' => 2400]);

    $this->actingAs($invoice->team->owner)
        ->post('/invoices/'.$invoice->id.'/charge')
        ->assertRedirect();

    Http::assertSent(function ($request) {
        return $request->url() === 'https://payments.example/charges'
            && $request['amount'] === 2400;
    });
});

Fake the sequence you mean. A 500 from the provider is a different test, and it should assert the invoice was not marked paid. This one asserts the body of the request that should have gone out.

Storage::fake() without an argument replaces the default disk from filesystems.php. If the PDF is written to a disk named invoices, pass that name: Storage::fake('invoices'). An assertion against the default disk then passes while the file landed somewhere else, which is the bug the path check was meant to catch.

Recap

You can store a PDF on a fake disk and refuse any HTTP host the test did not describe.

  • Storage::fake() replaces the disk. Assert the path the feature promised.
  • Http::preventStrayRequests() fails the test on a host you did not fake.
  • assertSent() belongs in the test that is about the amount, not in the test that only cares the file exists.

Check yourself · 3 questions

Question 1 of 3The code writes the PDF to the wrong filename. Storage::assertExists() is not called, and the test only checks that the disk is non-empty. What passes?

The PDF stays on the fake disk, and an unexpected host fails the test. Next, pin the clock the timestamp asserts against.

← PreviousFaking the queue

On this page

  • Swap both edges before the request
  • Assert the amount when the amount is the point
  • Recap
  • Check yourself

Test-driven Laravel

  • 1 Overview

The shape of a test

  • 2 What a feature test is for
  • 3 Arrange, act, assert
  • 4 Refreshing the database
  • 5 Factories that read like the domain
  • 6 Acting as a user

The paths that matter

  • 7 HTTP tests for happy paths
  • 8 Validation errors
  • 9 Authorisation

Edges and judgement

  • 10 Faking the mail
  • 11 Faking the queue
  • 12 Faking storage and HTTP
  • 13 Freezing time
  • 14 Datasets
  • 15 What not to test

Test-driven Laravel

Lessons

  1. 01Overview

The shape of a test

  1. 02What a feature test is for
  2. 03Arrange, act, assert
  3. 04Refreshing the database
  4. 05Factories that read like the domain
  5. 06Acting as a user

The paths that matter

  1. 07HTTP tests for happy paths
  2. 08Validation errors
  3. 09Authorisation

Edges and judgement

  1. 10Faking the mail
  2. 11Faking the queue
  3. 12Faking storage and HTTP
  4. 13Freezing time
  5. 14Datasets
  6. 15What not to test

Get the Friday email

One snippet and the week’s Laravel news, in your inbox every Friday morning. Unsubscribe whenever you like.

laravelmastery

Practical Laravel learning for working developers, made in the UK.

Learn

  • Snippets
  • Articles
  • Series

Stay current

  • News
  • Friday email
  • RSS feed

Company

  • About
  • Privacy
  • Terms
© 2026 Laravel Mastery. Independent and not affiliated with Laravel Holdings Inc.Designed and built by Half Shell Studios

We remember the videos you watch, where you left off, and which series lessons you mark as read, against this connection’s address. Nothing is stored until you agree.