Testing Laravel Vapor file uploads

February 27, 20202 min read

Testing classic file uploads, that are submitted directly to the server, in Laravel is extremely simple, as you can see in the example below:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testFileUpload()
    {
        Storage::fake();

        $response = $this->json('POST', '/avatar', [
            'file' => UploadedFile::fake()->image('photo.jpg'),
        ]);

        Storage::assertExists('photo.jpg');
    }
}

However if you’re are running your Laravel app on Vapor, you might know that files are never sent directly to your backend. Instead, users upload files directly to S3, into a tmp folder (which is configured to purge any files older than 24 hours) and just send the S3 file path to your backend for further processing.

After receiving the S3 file path in your API, you can move the file out of the tmp directory:

use Illuminate\Support\Facades\Storage;

Storage::copy(
    $request->input('key'),
    str_replace('tmp/', '', $request->input('key'))
);

Simulating S3 Direct Uploads in Tests

Since we have no S3 in our tests, we can place the files directly on our local system by using \Illuminate\Support\Facades\Storage::putFile() which in a testing environment will store files in storage/framework/testing/disks/local. This folder is also automatically purged each time you run your tests.

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testFileUpload()
    {
        Storage::fake();

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

        $filePath = Storage::putFile('tmp', $file);

        $response = $this->json('POST', '/avatar', [
            'key' => $filePath,
        ]);

        Storage::assertMissing($filePath);

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

As you can see, we’ve stored the file in a local tmp folder and sent its path to the API (just like we would store it on S3). Finally, we can test that the file was moved out of the tmp folder.


Thank you for reading this post! Subscribe below and get notified when new posts will be released or follow me on Twitter (@sandulat).


Join the Newsletter

Subscribe to get my latest posts by email.

I respect your privacy. Unsubscribe at any time.