【问题标题】:Mock file in Storage to download in Laravel存储中的模拟文件以在 Laravel 中下载
【发布时间】:2021-04-22 18:12:46
【问题描述】:

有没有办法使用 Laravels Storage::fake() 方法模拟文件?

我使用https://laravel.com/docs/5.7/mocking#storage-fake 作为我的测试的基础,它适用于上传。但是我的下载测试很难看,因为我每次都必须先运行我的上传路线,并使用模拟上传UploadedFile::fake()->image('avatar.jpg')。有没有办法跳过那部分并模拟文件直接存在于假存储系统中?

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);
}

【问题讨论】:

    标签: php laravel laravel-5.6


    【解决方案1】:

    我可能会迟到。但想帮助其他访问这个问题的人给出实施它的想法。

    这是一个带有一些断言的示例。

    <?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');
        }
    }
    

    【讨论】:

      【解决方案2】:

      是的,你可以使用 Laravel 的假文件存储功能(模拟):

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

      如果你想创建一个带有特定内容的文本/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');
      
      
      

      你可以在Illuminate\Http\Testing\FileFactory找到这个方法定义

      【讨论】:

        【解决方案3】:

        您可以直接创建一个新文件或复制一个特定的测试文件,例如:

        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');
        

        后一个函数将获取$file 并以给定名称avatar.jpg 将其复制到磁盘avatars 上的给定目录/。你可以阅读更多关于它的信息in the official documentation

        【讨论】:

          【解决方案4】:

          您可以使用固定装置来解决该问题。 Laravel 的测试框架本质上是 PHPUnit,所以我看不出它为什么不能工作。

          像这样定义你的测试:

          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);
              }
          }
          

          setUptearDown 分别在类中的每个测试之前和之后被调用。因此,在每个测试方法之前,setUp 将擦除avatars 假磁盘并运行请求。由于测试后无事可做(因为Storage::fake()如果磁盘已经存在则替换磁盘),方法为空;我把它留在这里纯粹是为了使示例完整。

          关于 PHPunit 的这个特性有一些非常好的文档on here

          关于把文件放在那里,一旦你的setUp 正常工作,没有什么能阻止你把文件扔在上面。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-26
            • 1970-01-01
            • 2017-09-05
            • 1970-01-01
            • 2022-01-15
            相关资源
            最近更新 更多