Ad

Laravel Test Unable To Find A File At Path Using Storage::fake()

- 1 answer

I have created my own 'disk' in config/filesystems.php which looks like so;

'uploads' => [
    'driver' => 'local',
    'root' => storage_path('app/public') . '/uploads'
],

This seems to work fine when in my controller, it uploads the file and returns a response. my code is as follows;

public function store(Request $request)
{
    if ($request->hasFile('filename')) {
        foreach ($request->file('filename') as $image) {
            $fileName = md5($image . microtime()) . '.' . $image->getClientOriginalExtension();
            $image->storeAs('', $fileName, 'uploads');
        }
    }

    // return goes here
}

but when I go to test my store method using the following code;

public function testUserCanSuccessfullySubmitSingleImage(): void
{
    Storage::fake('uploads');

    $this->postJson('/upload', [
        'filename' => UploadedFile::fake()->image('image1.jpg')
    ]);

    Storage::disk('uploads')->assertExists('image1.jpg');
    Storage::disk('uploads')->assertMissing('missing.jpg');
}

I get the following error;

Unable to find a file at path [image1.jpg].
Failed asserting that false is true.

I have followed a few tutorials, but they all say the same thing and im really lost.

Any help would be greatly appreciated.

Cheers

Ad

Answer

The problem is that you are renaming your file in the controller with md5($image . microtime()) so you cannot assert that image1.jpg exists since you changed the name.

What you could do is let laravel name the file and then check that in your test:

In your Controller:

Replace storeAs with store, store will generate a unique ID to serve as the file name.

public function store(Request $request)
{
    if ($request->hasFile('filename')) {
        foreach ($request->file('filename') as $image) {
            $image->store('', 'uploads');
        }
    }
}

In your test:

To assert if the image exists we will use the same method to generate the unique ID as laravel does when saving the image. Replace 'image1.jpg' with $image->hashName() in your assertion.

public function testUserCanSuccessfullySubmitSingleImage(): void
{
    Storage::fake('uploads');

    $this->postJson('/upload', [
        'filename' => $image = UploadedFile::fake()->image('image1.jpg')
    ]);

    Storage::disk('uploads')->assertExists($image->hashName());
    Storage::disk('uploads')->assertMissing('missing.jpg');
}

From the docs:

In web applications, one of the most common use-cases for storing files is storing user uploaded files such as profile pictures, photos, and documents. Laravel makes it very easy to store uploaded files using the store method on an uploaded file instance. Call the store method with the path at which you wish to store the uploaded file:

public function update(Request $request)
{
    $path = $request->file('avatar')->store('avatars');

    return $path;
}

There are a few important things to note about this example. Note that we only specified a directory name, not a file name. By default, the store method will generate a unique ID to serve as the file name. The file's extension will be determined by examining the file's MIME type. The path to the file will be returned by the store method so you can store the path, including the generated file name, in your database.

Ad
source: stackoverflow.com
Ad