Lumen 5.5 JSON API文件使用UploadedFile上传测试中断

时间:2017-09-29 09:29:21

标签: file-upload phpunit lumen

我正在使用Lumen构建文件上载JSON API并尝试编写phpunit API测试。

我遇到的问题是,只要我尝试使用["file" => new UploadedFile(TestUtils::tempPath('test.jpg'), 'test.jpg', "image\jpeg", 100, null, true)]构建的真实图像模拟文件上传并通过$this->json('POST', '/chunk', $data);发送, 我对上传的文件无能为力,因为它是一个数组,我收到错误Call to a member function move() on array in ...

奇怪的是,如果我使用UploadedFile::fake()->image('test.jpg')它会破坏我的请求,而我发送的其他数据在控制器中不可用。

如果我在控制器中找到了文件对象,它会显示“array(0){}”。我认为它与通过json('POST')传输有关,因为使用UploadedFileObject的单元测试可以直接成功运行。

如果我查看整个请求,则会显示:

["request"]=>
  object(Symfony\Component\HttpFoundation\ParameterBag)#52 (1) {
    ["parameters":protected]=>
    array(5) {
      ["chunkType"]=>
      string(4) "flow"
      ["flowIdentifier"]=>
      string(13) "Testing123Bnu"
      ["flowChunkNumber"]=>
      int(1)
      ["flowTotalChunks"]=>
      int(2)
      ["file"]=>
      array(0) {
      }
    }
  }

 ...

["files"]=>
object(Symfony\Component\HttpFoundation\FileBag)#71 (1) {
    ["parameters":protected]=>
    array(0) {
    }
  }

...

["content":protected]=> string(103) "{(otherData..), "file":{}}"

我不知道在这种情况下如何绕过这个或测试文件上传并且一直在搜索。 UploadedFile构造函数中的symfony测试模式无效。

这是我的测试:

    public function testChunkUpload_FlowChunk()
    {    
        $data = [   (otherData)
                    "file"              => new UploadedFile(TestUtils::tempPath('test.jpg'), 'test.jpg', "image\jpeg", 100, null, true)
                    //UploadedFile::fake()->image('test.jpg')
                ];

        $this->assertFileExists(TestUtils::tempPath('test.jpg'));

        $this->json('POST', '/chunk', $data);

        $this->assertEquals(200, $this->response->status());
        $this->assertEquals('application/json', $this->response->headers->get('Content-Type'));
    }

这是我控制器中的相关方法:

public function receiveChunk(Request $request){
    if (! $request->has('chunkType')) {
        return response()->json(["Invalid Chunk Type"], 400);
    }
    $data = $this->chunkNormalizer->normalizeInput($request->all());
    $chunk = $this->chunkFactory->createChunk(  (otherData)
                                                $data['fileHandle']);

    $this->fileAssembler->processChunk($chunk);

    return response()->json(["Success"], 200);    
}

并且在processChunk中发生错误:

public function processChunk(FileChunk $chunk){
    ...
    $chunkName  = "..." . ".chunk";

    $fileHandle = $chunk->getFileHandle();
    $fileHandle->move($this->assemblePath, $chunkName);
}

任何想法都将不胜感激!

2 个答案:

答案 0 :(得分:0)

编辑:奇怪的是,在laravel docs中," json"使用方法代替" call"同样。这可能是一个错误吗?或者仅仅是流明不兼容问题?  (Laravel Docs)

我已经想出如何让测试运行。我对如何通过JS供应商库上传文件的假设是错误的。实际上,文件块是使用XmlHttpRequest" multipart / formdata"上传的。而不是JSON。

我理解错误(JSON编码),但不理解来源。在理解它使用XmlHttpRequest之后,修复很简单。

工作测试:

public function testChunkUpload_FlowChunk()
{    
    $data = [   (otherData)
                "file"              => new UploadedFile(TestUtils::tempPath('test.jpg'), 'test.jpg', "image\jpeg", 100, null, true)
                //UploadedFile::fake()->image('test.jpg')
            ];

    $this->assertFileExists(TestUtils::tempPath('test.jpg'));

    $this->call('POST', '/chunk', $data);

    $this->assertEquals(200, $this->response->status());
    $this->assertEquals('application/json', $this->response->headers->get('Content-Type'));
}

我仍然不确定为什么使用UploadedFile :: fake() - > image(" xyz.jpg")有不同的效果,现在测试运行两种方法。

答案 1 :(得分:0)

这对我有用。很简单。这样可以在同一路径上提交数据(名称和电子邮件)和文件上传。

1。未经身份验证的条件

5*1000是文件大小(以KB为单位)。所以我用5 MB文件进行了测试。

use Faker\Factory as Faker;
use Illuminate\Http\UploadedFile;

class SampleTest extends TestCase
{
    public function testItCanCreateUser()
    {
        $faker = Faker::create();
        $data = array(
            'name' => $faker->name
        );
        $files = [
            'file' => UploadedFile::fake()->create('file.jpg', 5*1000)
        ];
        $response = $this->call('POST', '/chunk', $data, [], $files);
        $this->assertEquals(200, $response->getStatusCode());
    }
}

2。带有身份验证的条件(已登录用户)

use Faker\Factory as Faker;
use Illuminate\Http\UploadedFile;

class SampleTest extends TestCase
{
    public function testItCanUpdateProfileUser()
    {
        $faker = Faker::create();
        $data = array(
            'name' => $faker->name
        );
        $files = [
            'file' => UploadedFile::fake()->create('file.jpg', 5*1000)
        ];

        $headers = [
            'Accept' => 'application/json',
            'Authorization' => 'your-jwt-token'
        ];
        $servers = [];
        foreach ($headers as $k => $header) {
            $servers["HTTP_" . $k] = $header;
        }

        $response = $this->call('POST', '/chunk', $data, [], $files, $servers);
        $this->assertEquals(200, $response->getStatusCode());
    }
}

您需要在每个请求标头上添加HTTP_。我不确定为什么。但是会起作用。