Lumen 5.5 JSON API File Upload test breaks with UploadedFile

做~自己de王妃 提交于 2019-12-25 09:49:07

问题


I am building a file upload JSON API with Lumen and trying to write phpunit API tests.

The problem I am having though is that as soon as I try to simulate a file upload with a real image constructed like ["file" => new UploadedFile(TestUtils::tempPath('test.jpg'), 'test.jpg', "image\jpeg", 100, null, true)] and sending it via $this->json('POST', '/chunk', $data);, I can't do anything with the uploaded file because it is an array and I get the error Call to a member function move() on array in ...

Oddly enough if I use UploadedFile::fake()->image('test.jpg') it mangles my request and the other data I send with it isn't available in the controller.

If I dd the file object in my controller, it shows an "array(0){}". I am thinking it has something to do with the transfer via json('POST'), as unit tests that use an UploadedFileObject directly run successfully.

If I dd the entire request, it shows:

["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":{}}"

I have no idea how to circumvent this or test a file upload in this situation and have been searching for hours. The symfony test mode in the UploadedFile constructor has no effect.

Here is my test:

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

And here is the relevant method in my controller:

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

And the error occurs in processChunk:

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

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

Any ideas would be greatly appreciated!


回答1:


EDIT: Strangely enough, in the laravel docs the "json" method is used instead of "call" as well. Could this be an error? Or just a Lumen incompatability issue? (Laravel Docs)

I have figured out how to get the test to run. My assumptions about how the file is uploaded through the JS vendor library were wrong. In fact, the file chunks are uploaded with a XmlHttpRequest "multipart/formdata" and NOT as JSON.

I understood the error (JSON encoding), but not the source. After understanding that it uses an XmlHttpRequest, the fix was simple.

Working test:

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

I am still unsure about why using UploadedFile::fake()->image("xyz.jpg") had a different effect, now the test runs with both methods.



来源:https://stackoverflow.com/questions/46485894/lumen-5-5-json-api-file-upload-test-breaks-with-uploadedfile

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!