Search code examples
laravelfileunit-testingfakerlaravel-testing

Laravel faking file in the factory not working


I am developing a Web application using Laravel. I am unit testing my application that involves file operation. Have a look at my scenario below.

I have a download file action in the controller like this

public function downloadPersonalDetails(Order $order)
{
    if (! auth()->user()->can('downloadPersonalDetails', $order)) {
        abort(401);
    }

    return Storage::download($order->path);
}

I have the factory like this OrderFactory.php

$factory->define(Application::class, function (Faker $faker) {
    return [
        'first_name' => $faker->firstName,
        'last_name' => $faker->lastName,
        'email' => $faker->email,
        //other fields ....
        'path' => $faker->file('public/assets/files'),
});

This is my unit test to that download action

public function test_download_personal_details_file()
    {
        $user = //created a authorized valid user

        $order = factory(Order::class)
            ->create([
               'user' => $user->id
            ]);


        $this->actingAs($user)->get(route('order.personal_info.download', $order))->assertStatus(200);
    }

When I run the test I am getting error saying file does not exist.

File not found at path: tmp/439fe03f-f1c7-3b84-b123-d627d0395bd8.pdf

Why is that not working? How can I fix it and what is wrong with my code.


Solution

  • The faker will just create a fake filename however that filename will not correspond to any actual file. You will need to also fake it in the storage:

    public function test_download_personal_details_file()
    {
        $user = //created a authorized valid user
    
        $order = factory(Order::class)
            ->create([
               'user' => $user->id
            ]);
        \Storage::fake(config('filesystems.default')); //or any storage you need to fake
        \Storage::put($order->path, ''); //Empty file
    
        $this->actingAs($user)->get(route('order.personal_info.download', $order))->assertStatus(200);
    
    }
    

    This will create a file in the fake storage (so it won't actually write to disk).

    This requires Laravel 5.4+