Send file to Restful service in codeception

2019-06-24 02:20发布

问题:

I would like to test restful API test for file uploading.

I try to run:

 $I->sendPOST($this->endpoint, $postData, ['file' => 'example.jpg']);

and I would like it to behave the same as user sent example.jpg file in file input with name file but it doesn't seem to work this way. I'm getting:

[PHPUnit_Framework_ExceptionWrapper] An uploaded file must be an array or an instance of UploadedFile.

Is it possible to upload file using REST plugin in codeception? Documentation is very limited and it's hard to say how to do it.

I'm also testing API using Postman plugin to Google Chrome and I can upload file without a problem using this plugin.

回答1:

I was struggling with the same problem recently and found out that there is another way to solve the issue without using Symfony's UploadedFile class. You only need to pass the array with file data in the same format as if it were the $_FILES array. For example, this code works perfectly well for me:

$I->sendPOST(
    '/my-awesome-api',
    [
        'sample-field' => 'sample-value',
    ],
    [
        'myFile' => [
            'name' => 'myFile.jpg',
            'type' => 'image/jpeg',
            'error' => UPLOAD_ERR_OK,
            'size' => filesize(codecept_data_dir('myFile.jpg')),
            'tmp_name' => codecept_data_dir('myFile.jpg'),
        ]
    ]
);

Hope this helps someone and prevents from inspecting the framework's source code (which I was forced to do, as the docs skip such an important detail)



回答2:

After testing it seems to make it work we need to use UploadedFile object as file.

For example:

$path = codecept_data_dir();
$filename = 'example-image.jpg';

// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);

$mime = 'image/jpeg';

$uploadedFile = new \Symfony\Component\HttpFoundation\File\UploadedFile($path . $filename, $filename, $mime,
    filesize($path . $filename));

$I->sendPOST($this->endpoint, $postData, ['file' => $uploadedFile]);


回答3:

['file' => 'example.jpg'] format works too, but the value must be a correct path to existing file.

$path = codecept_data_dir();
$filename = 'example-image.jpg';

// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);

$I->sendPOST($this->endpoint, $postData, ['file' =>  $path . $filename]);


回答4:

The below worked for myself,

On server:

$uploadedResume= $_FILES['resume_uploader'];
$outPut = [];

        if (isset($uploadedResume) && empty($uploadedResume['error'])) {
            $uploadDirectory = 'uploads/users/' . $userId . '/documents/';
            if (!is_dir($uploadDirectory)) {
                @mkdir($uploadDirectory, 0777, true);
            }

            $ext = explode('.', basename($uploadedResume['name']));
            $targetPath = $uploadDirectory . md5(uniqid()) . '.' . end($ext);

            if (move_uploaded_file($uploadedResume['tmp_name'], $targetPath)) {
                $outPut[] = ['success' => 'success', 'uploaded_path' => $targetPath];
            }
        }
return json_encode($output);

Sorry for the long description code :P

On Testing side:

 //resume.pdf is copied in to tests/_data directory
$I->sendPOST('/student/resume', [], ['resume_uploader' => codecept_data_dir('resume.pdf') ]);


回答5:

@Yaronius's answer worked for me after I removed the following header from my test:

$I->haveHttpHeader('Content-Type', 'multipart/form-data');