如何在 Laravel 中测试同时使用 `Storage::put()` 和 `Storage::temporaryUrl()` 的路由?

jel*_*han 6 mocking laravel flysystem

我在 Laravel 7 中有一个路由,它将文件保存到 S3 磁盘并返回一个临时 URL。简化后的代码如下所示:

Storage::disk('s3')->put('image.jpg', $file);
return Storage::disk('s3')->temporaryUrl('image.jpg');
Run Code Online (Sandbox Code Playgroud)

我想为该路线编写一个测试。对于 Laravel,这通常很简单。我使用 模拟存储并Storage::fake('s3')使用 断言文件创建Storage::disk('s3')->assertExists('image.jpg')

假的存储不支持Storage::temporaryUrl()。如果尝试使用该方法,则会抛出以下错误:

此驱动程序不支持创建临时 URL。

一个常见的解决方法是使用 Laravel 的低级模拟 API,如下所示:

Storage::shouldReceive('temporaryUrl')
  ->once()
  ->andReturn('http://examples.com/a-temporary-url');
Run Code Online (Sandbox Code Playgroud)

LaraCasts线程和关于.Storage::fake()

有什么方法可以结合这两种方法来测试一条同时实现这两种方法的路线吗?

我想避免重新实现Storage::fake()。另外,我想避免在生产代码中添加检查,以便Storage::temporaryUrl()在环境正在测试时不调用。后一个是上面已经提到的LaraCasts 线程中提出的另一项工作。

kor*_*dor 8

我遇到了同样的问题并提出了以下解决方案:

$fakeFilesystem = Storage::fake('somediskname');
$proxyMockedFakeFilesystem = Mockery::mock($fakeFilesystem);
$proxyMockedFakeFilesystem->shouldReceive('temporaryUrl')
    ->andReturn('http://some-signed-url.test');
Storage::set('somediskname', $proxyMockedFakeFilesystem);
Run Code Online (Sandbox Code Playgroud)

现在Storage::disk('somediskname')->temporaryUrl('somefile.png', now()->addMinutes(20))返回http://some-signed-url.test,我实际上可以将文件存储在提供的临时文件系统中,Storage::fake()而无需任何进一步的更改。


abe*_*aut -1

您可以关注这篇文章https://laravel-news.com/testing-file-uploads-with-laravel,并将其与您的需求混合在一起,如下所示;模拟似乎是累积的:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    public function testAvatarUpload()
    {
        $temporaryUrl = 'http://examples.com/a-temporary-url';

        Storage::fake('avatars');

        /*
         * >>> Your Specific Asserts HERE
         */
        Storage::shouldReceive('temporaryUrl')
            ->once()
            ->andReturn($temporaryUrl);

        $response = $this->json('POST', '/avatar', [
            'avatar' => UploadedFile::fake()->image('avatar.jpg')
        ]);


        $this->assertContains($response, $temporaryUrl);


        // Assert the file was stored...
        Storage::disk('avatars')->assertExists('avatar.jpg');

        // Assert a file does not exist...
        Storage::disk('avatars')->assertMissing('missing.jpg');
    }
}

Run Code Online (Sandbox Code Playgroud)

控制台功能测试的另一个例子: