Lennart
Lennart

Reputation: 33

How to test Laravel media upload with form validation

Some time ago i wrote a test for my media upload in my laravel project. The test just sends a post request with an image to a route and checks if the server sends a 200 status code.

use Illuminate\Http\UploadedFile;

/** @test */
public function it_can_upload_image()
{
    $response = $this->post('/media', [
        'media' => new UploadedFile(__DIR__ . "/test_png.png", 'test_png.png'),
    ]);
    $response->assertStatus(200);
}

When I add a validation rule for the media post parameter the server returns a 302 status code and the test fails. However when I test the media upload by hand in the browser everything works fine.

public function uplaodMedia($request) 
{
    $request->validate([
        'media' => 'required'
    ]);

    // ...
}

The behavior of a request in a test seems to be different than an actual browser request. However, I have not managed to solve the issue until now. Did anyone ran into something similar before?

Upvotes: 1

Views: 605

Answers (1)

Remul
Remul

Reputation: 8242

You need to pass true for the $test argument when creating a new UploadedFile for your test:

new UploadedFile(__DIR__ . "/test_png.png", 'test_png.png', null, null, true)

Here you can find the constructor definition:

/**
 * @param bool        $test         Whether the test mode is active
 *                                  Local files are used in test mode hence the code should not enforce HTTP uploads
 */
public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false)

Although I don't understand why you want to use a real image for this test, Laravel provides a built in way to easily test file uploads.

From the docs:

The Storage facade's fake method allows you to easily generate a fake disk that, combined with the file generation utilities of the UploadedFile class, greatly simplifies the testing of file uploads.

So your test could be simplified to the following:

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

/** @test */
public function it_can_upload_image()
{        
    Storage::fake();

    $this->post('/media', ['media' => UploadedFile::fake()->image('test_png.png')])
        ->assertStatus(200);
}

Upvotes: 2

Related Questions