Summer Sale! All accounts are 50% off this week.

Cvetan's avatar

Storage::fake('public') affects actual public storage in storage/app/public

As I wrote in title, this happens when I trigger Storage::fake('public') and make some manipulations, there(delete existing, add new files) actual files in public directory are affected.

What can be the source of this, am I doing something wrong? Here is a brief snippet, which triggers this:

Storage::fake('public');
Storage::delete('public/uploads/users/default-avatar.jpg')  // <- actual file that exists in storage/app/public/uploads/users/default-avatar.jpg

I haven't change no configuration related filesystems I am using default config from Laravel installation.

0 likes
4 replies
LaryAI's avatar
Level 58

When you use Storage::fake('public') in your tests, it should create a temporary disk that mimics the public disk, and any operations performed on this fake disk should not affect your actual files. However, if your actual files are being affected, it suggests that the fake storage is not being properly set up or used.

Here are a few things to check and a solution to ensure that Storage::fake('public') works as expected:

  1. Ensure Proper Namespace and Imports: Make sure you are using the correct namespaces and imports in your test file.

  2. Correct Usage of Storage::fake: Ensure that Storage::fake('public') is called before any storage operations in your test.

  3. Check for Configuration Issues: Ensure that your config/filesystems.php is correctly set up and that the public disk is properly configured.

Here is a corrected and complete example of how you might write your test:

use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class YourTest extends TestCase
{
    public function test_storage_fake()
    {
        // Fake the public disk
        Storage::fake('public');

        // Perform storage operations
        Storage::delete('public/uploads/users/default-avatar.jpg');

        // Assert that the file was deleted from the fake disk
        Storage::disk('public')->assertMissing('uploads/users/default-avatar.jpg');
    }
}

Explanation:

  1. Faking the Disk:

    Storage::fake('public');
    

    This line ensures that any subsequent storage operations on the public disk are performed on a temporary, in-memory disk rather than the actual filesystem.

  2. Performing Operations:

    Storage::delete('public/uploads/users/default-avatar.jpg');
    

    This operation will now affect the fake disk, not the actual storage/app/public directory.

  3. Assertions:

    Storage::disk('public')->assertMissing('uploads/users/default-avatar.jpg');
    

    This assertion checks that the file is missing from the fake disk, ensuring that your test is working as expected.

Additional Tips:

  • Run Tests in Isolation: Ensure that your tests are not affecting each other by running them in isolation.
  • Clear Cache: Sometimes, configuration caching can cause unexpected behavior. Clear the cache using php artisan config:clear.

By following these steps, you should be able to use Storage::fake('public') without affecting your actual files in storage/app/public.

s4muel's avatar

if you haven't changed the filesystem.php config, then probably the local disk is used and not public.

what happens if you change it like this?

//instead of this
//Storage::delete('public/uploads/users/default-avatar.jpg');

//try this
Storage::disk('public')->delete('uploads/users/default-avatar.jpg');

just check the path, i just assume the public sits in the "public" subfolder

Cvetan's avatar

@s4muel Paths is ok, it is like this app/public/uploads/users/default-avatar.jpg. When I modify the test like this:

$image = 'uploads/users/default-avatar.jpg';

Storage::fake('public');

Storage::disk('public')->exists($image);
Storage::disk('public')->delete($image);
$this->assertFalse(Storage::disk('public')->exists($image));

It works without touching actual files. However this makes me wonder what is the problem with Storage::delete method, does it use default driver (local) in this instance by default, or how is the public disk different from local in this matter?

s4muel's avatar

@Cvetan your local disk is coincidentally a parent folder of public disk, that is why Storage::delete('public/... works and link/path is fine. but faking it like this Storage::fake('public'); fakes the public disk explicitly. And Storage::delete('public/... doesn't use public disk (it is like using Storage::storage('local')->delete('public/...), so the fake is never applied/used

Please or to participate in this conversation.