Search code examples
phpunitcodeceptionweb-api-testing

Testing file uploads with codeception


Problem:

No data and files are coming through to the Silex application when a request is made from codeception test using the REST module with PhpBrowser driver.

    // ApiTester $I
    $I->wantTo('Submit files');

    // prepare:
    $data = ['key' => 'value'];
    $files = [
        'file_key' => 'path/to/file.doc',
        'file2_key' => 'path/to/file2.doc'
    ];

    // act:
    $I->haveHttpHeader('Content-Type', 'multipart/form-data');
    $I->sendPOST('/attachments/', $data, $files);

Current response

 I have http header "Content-Type","multipart/form-data"
 I send post "/attachments/",{"key":"value"},{"file_key":"/path/to/file/...}
  [Request] POST http://localhost/attachments/ {"key":"value"}
  [Request Headers] {"Content-Type":"multipart/form-data"}
  [Page] http://localhost/attachments/
  [Response] 400
  [Request Cookies] []
  [Response Headers] {"Date":["Tue, 25 Oct 2016 09:15:31 GMT"],"Server":["Apache/2.4.10 (Debian)"],"Cache-Control":["no-cache"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization"],"Access-Control-Allow-Methods":["GET,PATCH,PUT,POST,HEAD,DELETE,OPTIONS"],"Content-Length":["1235"],"Connection":["close"],"Content-Type":["application/json"]}
  [Response] {"status":400,"meta":{"time":"2016-10-25 09:15:31"},"title":"Invalid Request","errors":"No data received","details":{"error_class":"Symfony\Component\HttpKernel\Exception\BadRequestHttpException"

Tried:

  • changing the Content-Type header
  • changing files array passed to sendPOST to an array of:
    • file paths file objects ( UploadedFile )
    • file arrays

The test works with Silex driver, but that won't be an option on the CI server. Also we've checked with Postman and the API route works as intended, files are sent and all good.


Solution

  • The actual problems:

    • $I->haveHttpHeader('Content-Type', 'multipart/form-data'); overwrites the Content-Type as it should be set by the http library (in phpbrowser is guzzle) to include the boundary, it's related to this.
    • Also be mindful that the $I->header does not reset after each request, to unset it use $I->deleteHeader('Content-Type');

    Solution

    • Don't set the 'Content-Type' headers when sending files.