简体   繁体   English

存储中的模拟文件以在 Laravel 中下载

[英]Mock file in Storage to download in Laravel

Is there a way to mock a file using Laravels Storage::fake() method?有没有办法使用 Laravels Storage::fake()方法模拟文件?

I have used https://laravel.com/docs/5.7/mocking#storage-fake as a base for my tests, which works fine for uploads.我已经使用https://laravel.com/docs/5.7/mocking#storage-fake作为我测试的基础,它适用于上传。 But my download tests are ugly as I have to run my upload route first every time with a mock upload UploadedFile::fake()->image('avatar.jpg') .但是我的下载测试很难看,因为我每次都必须先使用模拟上传UploadedFile::fake()->image('avatar.jpg')运行我的上传路线。 Is there a way to skip that part and mock the file to exist directly in the fake storage system?有没有办法跳过那部分并模拟文件直接存在于假存储系统中?

public function testAvatarUpload()
{
    Storage::fake('avatars');

    // This is the call I would like to change into a mocked existing uploaded file
    $uploadResponse = $this->json('POST', '/avatar', [
        'avatar' => UploadedFile::fake()->image('avatar.jpg')
    ]);

    // Download the first avatar
    $response = $this->get('/download/avatar/1');

    $response->assertStatus(200);
}

I might be late here.我可能来晚了。 but wanted to help others visiting this question to give an idea of implementing it.但想帮助访问此问题的其他人提供实施它的想法。

Here is a sample with some assertions.这是一个带有一些断言的示例。

<?php

namespace Tests\Feature\Upload;

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

class SampleDownloadTest extends TestCase
{
    /**
     * @test
     */
    public function uploaded_file_downloads_correctly()
    {
        //keep a sample file inside projectroot/resources/files folder
        //create a file from it
        $exampleFile = new File(resource_path('files/test-file.png'))
        //copy that file to projectroot/storage/app/uploads folder
        Storage::putFileAs('/uploads', $exampleFile, 'test-file.png');

        //make request to file download url to get file 
        $response = $this->get("/files/file/download/url");

        //check whethe response was ok
        $response->assertOk();
        $response->assertHeader('Content-Type', 'image/png')
        //check whether file exists in path
        Storage::assertExists('/uploads/test-file.png');
        //do some more assertions.....
        //after test delete the file from storage path
        Storage::delete('uploads/test-file.png');
        //check whether file was deleted
        Storage::assertMissing('/uploads/test-file.png');
    }
}

You could just create a new file directly or copy a specific test file for example:您可以直接创建一个新文件或复制一个特定的测试文件,例如:

use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;

// for simple text files or if the content doesn't matter
Storage::disk('avatars')->put('avatar.jpg', 'some non-jpg content');

// if you need a specific file for your test
$file = new File(base_path('tests/resources/avatar.jpg'));
Storage::disk('avatars')->putFileAs('/', $file, 'avatar.jpg');

The latter function will take the $file and copy it under the given name avatar.jpg to the given directory / on the disk avatars .后者的功能将在$file和给定的名义复制avatar.jpg到指定目录/磁盘上的avatars You can read more about it in the official documentation .您可以在官方文档中阅读更多相关信息。

What you could use to solve that problem is fixtures.你可以用来解决这个问题的是夹具。 Laravel's testing framework is essentially PHPUnit, so I see no reason why it would not work. Laravel 的测试框架本质上是 PHPUnit,所以我看不出它行不通的原因。

define your test like so:像这样定义你的测试:

use Tests\TestCase;

class ExampleTest extends TestCase {
    protected function setUp() {
        parent::setUp();
        Storage::fake('avatars');
        $uploadResponse = $this->json('POST', '/avatar', [
          'avatar' => UploadedFile::fake()->image('avatar.jpg')
        ]);
    }
    protected function tearDown() {
        parent::tearDown();
    }
    public function testAvatarUpload() {
        // Download the first avatar
        $response = $this->get('/download/avatar/1');

        $response->assertStatus(200);
    }
}

setUp and tearDown get called, respectively, before and after each test in the class. setUptearDown分别在类中的每个测试之前和之后被调用。 So, before each test method, setUp will wipe the avatars fake disk and run the request.因此,在每个测试方法之前, setUp将擦除avatars假磁盘并运行请求。 As there is nothing to do after a test (since Storage::fake() replaces the disk if it already exists), the method is empty;由于测试后无事可做(因为Storage::fake()替换已经存在的磁盘),该方法为空; I left it here purely to make the example complete.我把它留在这里纯粹是为了使示例完整。

There's some pretty good documentation on here about this feature of PHPunit.关于 PHPunit 的这个特性, 这里有一些非常好的文档。

Regarding putting the file on there, once you have your setUp working correctly, there's nothing stopping you from throwing the file on it.关于把在那里的文件,一旦你有你setUp正常工作,并没有什么东西扔上的文件阻止你。

Yes, you can use fake file storage feature of Laravel (mocking):是的,您可以使用 Laravel 的假文件存储功能(模拟):

use Illuminate\Http\UploadedFile;

$file = UploadedFile::fake()->create('filename.ext', $sizeInKb)->store('filename.ext');

If you want to create a text/csv file with a specific content you can use this:如果要创建具有特定内容的 text/csv 文件,可以使用以下命令:

use Illuminate\Http\UploadedFile;

$header = 'a,b,c';
$row1 = 'x,y,z';
$row2 = 's,f,t';
$row3 = 'r,i,o';

$content = implode("\n", [$header, $row1, $row2, $row3]);

$file = UploadedFile::fake()->createWithContent('filename.ext', $content)->store('filename.ext');


You can find this methods definitions in Illuminate\\Http\\Testing\\FileFactory你可以在Illuminate\\Http\\Testing\\FileFactory找到这些方法的定义

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM