Currently Available: Need a skilled Software Developer for your next project?
Categories
Laravel

Testing File Uploads with Laravel Storage Fakes

A Laravel feature test sends a request through a route and its upload handler. When the request includes an uploaded file, the handler may write it to a local directory or cloud service. A storage disk is a named Laravel configuration that points to a storage location. Storage::fake() replaces the selected disk with a local testing disk, so the test can check the file without writing to that disk’s normal destination.

UploadedFile::fake() creates a test file to pair with the storage fake. Send it through the usual request, then assert that Laravel stored the file at the expected path. Laravel’s file storage documentation describes the fake as a local testing disk whose temporary directory is cleaned by default. The fake uses temporary local storage rather than an in-memory filesystem.

Run the upload test against a fake disk

Use the same disk, directory, and filename behavior as the upload handler. The fake redirects writes only for the disk you name. If you fake avatars, writes to another disk still go to that disk’s configured destination.

A practical feature-test workflow is:

  1. Check the upload handler. Find which disk the handler writes to and where it saves the file. The handler might preserve the client’s filename, generate a name, or save the file in a subdirectory.
  2. Fake that disk before sending the request. This directs the upload’s storage write to the testing disk.
  3. Create a fake uploaded file. Use UploadedFile::fake()->image() for an image or UploadedFile::fake()->create() for another file type. Laravel lets you set a fake image’s dimensions and size. PHP’s GD extension must be available to generate a fake image.
  4. Submit the file through the route. A feature test sends a request through the route that handles the upload, rather than calling the storage code alone.
  5. Check the response and stored path. Assert the response expected from the route, then verify that the file exists on the faked disk.

This example assumes the handler stores the upload on the avatars disk, at its root, using Laravel’s generated hash name:

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

test('avatars can be uploaded', function () {
    Storage::fake('avatars');

    $file = UploadedFile::fake()->image('avatar.jpg');

    $response = $this->post('/avatar', [
        'avatar' => $file,
    ]);

    $response->assertSuccessful();

    Storage::disk('avatars')->assertExists($file->hashName());
});

The example follows Laravel’s documented file upload test pattern. If the handler stores the file in a directory, include that directory in the assertion, such as avatars/{$file->hashName()}. If the handler chooses a custom filename, assert that path instead. The expected path comes from the handler’s storage call, not necessarily from the filename submitted by the client.

Assert the storage result you expect

assertExists($path) checks that a file or directory exists on the faked disk. Use it to verify the specific path the handler should create. Laravel’s filesystem assertions also let a test check that a path is absent with assertMissing($path). Use assertCount($directory, $count) to count files in a directory. A test can also check whether a directory or disk is empty. The filesystem testing documentation describes these assertions.

Choose an assertion that matches the behavior under test. For a single upload, checking the expected file path is direct. For a handler that should leave a directory unchanged when validation fails, assert that the expected file is missing or that the directory remains empty. For a handler that stores multiple files, check the expected count as well as any paths that matter.

Keep tests away from normal storage destinations

Storage::fake('avatars') replaces the selected disk with a local testing disk. The test stays isolated from that disk’s normal destination when the upload code writes through the disk that was faked. If the handler writes to a different disk, fake that disk instead; otherwise, the fake does not protect that write. Laravel’s Storage facade API describes fake as replacing the given disk with a local testing disk.

For routine tests, use fake() rather than persistentFake(). Laravel documents fake() as cleaning the files in its temporary directory by default; persistentFake() is available when a test intentionally needs files to persist. Because the fake uses local temporary storage, it still writes to the local filesystem. It also does not test whether a real cloud provider, its credentials, or its network connection work.

The examples here use Laravel 13.x documentation. If a project uses another Laravel version, check that version’s filesystem and HTTP testing documentation for the available methods and behavior.

What I'm building

Delegate tasks. Get software.

Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.

Take a look at vroni.com

Email updates

Usually a new article and a few links I found interesting.

No spam. Unsubscribe with one click.

Leave a Reply

Your email address will not be published. Required fields are marked *