4

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

Storage::disk('s3')->put('image.jpg', $file);
return Storage::disk('s3')->temporaryUrl('image.jpg');

我想为那条路线写一个测试。对于 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');

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

有什么方法可以结合这两种方法来测试两者兼而有之的路线吗?

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

4

3 回答 3

3

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

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

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

于 2021-04-02T22:52:15.710 回答
1

回复上面的@abenevaut 答案,以及评论中遇到的问题——对 Storage::disk() 的调用也需要模拟——比如:

    Storage::fake('s3');
    Storage::shouldReceive('disk')
        ->andReturn(
            new class()
            {
                public function temporaryUrl($path)
                {
                    return 'https://mock-aws.com/' . $path;
                }
            }
        );

    $expectedUrl = Storage::disk('s3')->temporaryUrl(
        'some-path',
        now()->addMinutes(5)
    );

    $this->assertEquals('https://mock-aws.com/some-path', $expectedUrl);
于 2021-03-23T13:06:58.543 回答
-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');
    }
}

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

于 2020-08-31T09:40:35.303 回答