phplaraveltestingfile-uploadxunit

Laravel: How to test file upload with a real file?


I got a controller and a request class to handle a simple file upload. I am using a test method to test the functioning of the upload. So far so good. The controller part, which does not get reached (because validation fails (importfile needs to be a file.)), looks like:

public function importCustomers(ImportCustomersRequest $request)
{
    dump('importCustomers called!');

The relevant parts of the request class ImportCustomersRequest is this:

public function rules(): array
{
    dump('importfile', $this->importfile);

    return [
        'importfile' => 'required|file',
    ];
}

The code used for testing is:

$file = UploadedFile::fake()->createWithContent('customer.csv', 'id;name;group\n9999;Customer1;');

// other approachs that did not work:
// $file = UploadedFile::fake()->create('customer.csv')
//
// testing with a real file would be ok too (the file exists!) - but nada (i receive the file content instead of an UploadedFile):
// $file = Storage::path('development/customers.csv')

$response = $this->post(route('import.customers', ['importfile' => $file]));
$response->assertStatus(302);
...

Dumping the importfile value in the request class using the upload via frontend (and a real file) yields a desired

Illuminate\Http\UploadedFile {#2053 ▼
  -test: false
  -originalName: "customers.csv"
  -mimeType: "text/csv"
  -error: 0
  ...

Using the phpunit test from above gives me

array:2 [
  "name" => "customer.csv"
  "sizeToReport" => "67"
]

which obviously fails.

How am i able to upload a test file (preferably a real file with content) that passes validation (an UploadedFile)?


Solution

  • This problem was easier solved than expected. I had to put the file content as a parameter of the request and not the route. See:

    $file = UploadedFile::fake()->createWithContent('customer.csv', 'id;name;group\n9999;Customer1;');
    $response = $this->post(route('import.customers'), ['importfile' => $file]);