【问题标题】:How to test file upload in Laravel 5.2如何在 Laravel 5.2 中测试文件上传
【发布时间】:2016-07-24 07:38:11
【问题描述】:

我正在尝试测试上传 API,但每次都失败:

测试代码:

$JSONResponse = $this->call('POST', '/upload', [], [], [
    'photo' => new UploadedFile(base_path('public/uploads/test') . '/34610974.jpg', '34610974.jpg')
]);

$this->assertResponseOk();
$this->seeJsonStructure(['name']);

$response = json_decode($JSONResponse);
$this->assertTrue(file_exists(base_path('public/uploads') . '/' . $response['name']));

文件路径为/public/uploads/test/34610974.jpg

这是控制器中的我的上传代码:

$this->validate($request, [
    'photo' => 'bail|required|image|max:1024'
]);

$name = 'adummyname' . '.' . $request->file('photo')->getClientOriginalExtension();

$request->file('photo')->move('/uploads', $name);

return response()->json(['name' => $name]);

我应该如何在 Laravel 5.2 中测试文件上传?如何使用call方法上传文件?

【问题讨论】:

标签: php unit-testing laravel testing upload


【解决方案1】:

我认为这是最简单的方法

$file=UploadedFile::fake()->image('file.png', 600, 600)];
$this->post(route("user.store"),["file" =>$file));

$user= User::first();

//check file exists in the directory
Storage::disk("local")->assertExists($user->file); 

我认为在测试中删除上传文件的最佳方法是使用 tearDownAfterClass 静态方法, 这将删除所有上传的文件

use Illuminate\Filesystem\Filesystem;

public static function tearDownAfterClass():void{
        $file=new Filesystem;
        $file->cleanDirectory("storage/app/public/images");
}

【讨论】:

    【解决方案2】:

    laravel 文档为您何时想要测试假文件提供了答案。当您想在 laravel 6 中使用真实文件进行测试时,您可以执行以下操作:

    namespace Tests\Feature;
    
    use Illuminate\Http\UploadedFile;
    use Tests\TestCase;
    
    class UploadsTest extends TestCase
    {
        // This authenticates a user, useful for authenticated routes
        public function setUp(): void
        {
            parent::setUp();
            $user = User::first();
            $this->actingAs($user);
        }    
    
        public function testUploadFile()
        {
            $name = 'file.xlsx';
            $path = 'absolute_directory_of_file/' . $name;
            $file = new UploadedFile($path, $name, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', null, true);
            $route = 'route_for_upload';
            // Params contains any post parameters
            $params = [];
            $response = $this->call('POST', $route, $params, [], ['upload' => $file]);
            $response->assertStatus(200);
        }  
    
    }
    

    【讨论】:

      【解决方案3】:

      在 Laravel 5.4 中,你也可以使用 \Illuminate\Http\UploadedFile::fake()。下面是一个简单的例子:

      /**
       * @test
       */
      public function it_should_allow_to_upload_an_image_attachment()
      {
          $this->post(
              action('AttachmentController@store'),
              ['file' => UploadedFile::fake()->image('file.png', 600, 600)]
          );
      
          /** @var \App\Attachment $attachment */
          $this->assertNotNull($attachment = Attachment::query()->first());
          $this->assertFileExists($attachment->path());
          @unlink($attachment->path());
      }
      

      如果你想伪造不同的文件类型,你可以使用

      UploadedFile::fake()->create($name, $kilobytes = 0)
      

      更多信息直接在Laravel Documentation.

      【讨论】:

      • 但是如果只询问特定的 MIME 类型如 mp3,create() 方法不会通过验证...
      【解决方案4】:

      您可以在link找到此代码

      设置

      /**
       * @param      $fileName
       * @param      $stubDirPath
       * @param null $mimeType
       * @param null $size
       *
       * @return  \Illuminate\Http\UploadedFile
       */
      public static function getTestingFile($fileName, $stubDirPath, $mimeType = null, $size = null)
      {
          $file =  $stubDirPath . $fileName;
      
          return new \Illuminate\Http\UploadedFile\UploadedFile($file, $fileName, $mimeType, $size, $error = null, $testMode = true);
      }
      

      用法

          $fileName = 'orders.csv';
          $filePath = __DIR__ . '/Stubs/';
      
          $file = $this->getTestingFile($fileName, $filePath, 'text/csv', 2100);
      

      文件夹结构:

      - MyTests
        - TestA.php
        - Stubs
          - orders.csv
      

      【讨论】:

        【解决方案5】:

        创建UploadedFile 的实例时,将最后一个参数$test 设置为true

        $file = new UploadedFile($path, $name, filesize($path), 'image/png', null, true);
                                                                                   ^^^^
        

        这是一个工作测试的简单示例。它希望您在tests/stubs 文件夹中有一个存根test.png 文件。

        class UploadTest extends TestCase
        {
            public function test_upload_works()
            {
                $stub = __DIR__.'/stubs/test.png';
                $name = str_random(8).'.png';
                $path = sys_get_temp_dir().'/'.$name;
        
                copy($stub, $path);
        
                $file = new UploadedFile($path, $name, filesize($path), 'image/png', null, true);
                $response = $this->call('POST', '/upload', [], [], ['photo' => $file], ['Accept' => 'application/json']);
        
                $this->assertResponseOk();
                $content = json_decode($response->getContent());
                $this->assertObjectHasAttribute('name', $content);
        
                $uploaded = 'uploads'.DIRECTORY_SEPARATOR.$content->name;
                $this->assertFileExists(public_path($uploaded));
        
                @unlink($uploaded);
            }
        }
        
        ➔ phpunit 测试/UploadTest.php Sebastian Bergmann 和贡献者的 PHPUnit 4.8.24。 . 时间:2.97 秒,内存:14.00Mb 好的(1 个测试,3 个断言)

        【讨论】:

        • 应该可以,但是不行。 $request->file('photo') 确实有 UploadFile 对象,但是这个对象中的$test 有它的默认值false。奇怪,因为新的 UploadedFile 有 $test = true 参数。
        • 以上答案对于 > 5.2.14 是不够的。你能在这里找到正确的答案:stackoverflow.com/questions/36857800/…
        • 应该是$file = new UploadedFile($path, $name, 'image/png', filesize($path), null, true);
        • 对于Symfony 4.1,正确的实现是$file = new UploadedFile($path, $name, 'image/png', null, true);
        猜你喜欢
        • 1970-01-01
        • 2019-10-27
        • 2019-12-28
        • 2016-07-20
        • 2016-04-23
        • 2016-08-15
        • 2016-06-09
        • 2018-03-24
        • 2016-01-21
        相关资源
        最近更新 更多