I have a issue while trying to mock multi Storage
in laravel test enviromnment.
Here is my my code:
public function sftp ( Sibling $sibling ) {
$file_paths = Storage::build($sibling->config)
->files($this->track->track_token);
Storage::disk('public')
->makeDirectory($this->track->track_token);
foreach ( $file_paths as $file_path ) {
$file_content = Storage::build($sibling->config)
->get($file_path);
TrackMp3::query()
->where('track_id' , $this->track->id)
->where('file_name' , basename($file_path))
->update([
'downloaded_at' => now() ,
]);
Storage::disk('public')
->put($file_path , $file_content);
}
}
Here is my test case:
public function test_sftp_works_when_track_exists_in_sibling () {
$track_token = md5('sample');
$track_320 = UploadedFile::fake()
->create('track_320.mp3')
->getContent();
$track_160 = UploadedFile::fake()
->create('track_160.mp3')
->getContent();
$track_96 = UploadedFile::fake()
->create('track_96.mp3')
->getContent();
$track_demo = UploadedFile::fake()
->create('track_demo.mp3')
->getContent();
$sibling = SiblingFactory::new()
->create();
$public_disk = Storage::fake('public');
$sibling_disk = Storage::fake('sibling');
Storage::shouldReceive('build')
->with($sibling->config)
->andReturn($sibling_disk);
$sibling_disk->put($track_token . '/track_320.mp3' , $track_320);
$sibling_disk->put($track_token . '/track_160.mp3' , $track_160);
$sibling_disk->put($track_token . '/track_96.mp3' , $track_96);
$sibling_disk->put($track_token . '/track_demo.mp3' , $track_demo);
$track = TrackFactory::new()
->md5Fetched()
->has(TrackMp3Factory::new([ 'md5' => md5_file($sibling_disk->path($track_token . '/track_320.mp3')) ])
->fileName320())
->has(TrackMp3Factory::new([ 'md5' => md5_file($sibling_disk->path($track_token . '/track_160.mp3')) ])
->fileName160())
->has(TrackMp3Factory::new([ 'md5' => md5_file($sibling_disk->path($track_token . '/track_96.mp3')) ])
->fileName96())
->has(TrackMp3Factory::new([ 'md5' => md5_file($sibling_disk->path($track_token . '/track_demo.mp3')) ])
->fileNameDemo())
->create([ 'track_token' => $track_token ]);
Storage::fake('public'); // ----> Error happend here
Artisan::call('download');
}
Here is the error:
Mockery\Exception\BadMethodCallException: Received Mockery_2_Illuminate_Filesystem_FilesystemManager::createLocalDriver(), but no expectations were specified
C:\Development\projects\track-download-manager\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:353
C:\Development\projects\track-download-manager\vendor\laravel\framework\src\Illuminate\Support\Facades\Storage.php:107
C:\Development\projects\track-download-manager\tests\Feature\DownloadCommandTest.php:55
you've called Storage::fake() more than once. first for sibling and then for public. When you call it the second time, Laravel is attempting to create a local disk and because you've mocked the Storage facade earlier, the test breaks.
The key is to set up your fakes before you set up any mocks.
If you're not checking the interaction with
Storage::build
in this test and only need to make sure that files are correctly placed on the sibling and public disks, consider removing theshouldReceive('build')
mocking.If you still face issues, you can reset the mocked instance after you're done with it to ensure no side effects for subsequent calls.