如何使用 API 平台对 GraphQL 文件上传进行单元测试?
How can I Unit Test GraphQL file Upload with API Platform?
除了针对我的 GraphQL API 平台后端的其他测试之外,我还尝试测试文件上传。我不太确定 ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client
class 是否能够促进此测试,或者是否应该使用 Symfony\Component\HttpFoundation\File\UploadedFile
来提供用于 REST 操作的测试文件。
这就是我在整理这个测试方面的大致情况。 (为简化起见,删除了一些不相关的部分)
public function testCreateMediaObject(): void {
$file = new UploadedFile('fixtures/files/logo.png', 'logo.png');
$client = self::createClient();
$gql = <<<GQL
mutation UploadMediaObject($file: Upload!) {
uploadMediaObject(input: {file: $file}) {
mediaObject {
id
contentUrl
}
}
}
GQL;
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => null],
'map' => ['0' => ['variables.file']],
'0' => $file,
]
]);
dd($response);
}
我收到的回复似乎表明文件没有按预期包含在内。像...
Variable "$file" of non-null type "Upload!" must not be null.
或者.. 如果我尝试通过直接在 variables
属性...
中直接分配来附加文件
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => $file],
]
]);
然后...
Variable "$file" got invalid value []; Expected type Upload; Could not get uploaded file, be sure to conform to GraphQL multipart request specification. Instead got: []
在我最近的尝试中,我在筛选 graphql 代码后做了很多改动...
$formFields = [
'operations' => '{ "query": "mutation ($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => "{'0': ['variables.file']}",
'0' => DataPart::fromPath(__DIR__.'/../../fixtures/files/logo.png'),
];
$formData = new FormDataPart($formFields);
$response = $client->request('POST', '/api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'body' => $formData->bodyToString(),
]);
最后一次尝试的问题是服务器没有看到任何正文参数。所以我收到异常
'GraphQL multipart request does not respect the specification.'
在 parseMultipartRequest
方法中的 /api-platform/core/src/GraphQl/Action/EntrypointAction.php
中找到。
经过几个小时的调试,我找到了这个解决方案:
$formData = new FormDataPart();
$file = new UploadedFile('src/DataFixtures/files/test.txt', 'test.txt');
$response = $this->$client->request('POST', 'api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'extra' => [
'parameters' => [
'operations' => '{ "query": "mutation UploadMediaObject($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => '{ "0": ["variables.file"] }',
'0' => @$file,
],
'files' => [
$file,
],
],
]);
参考:
除了针对我的 GraphQL API 平台后端的其他测试之外,我还尝试测试文件上传。我不太确定 ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client
class 是否能够促进此测试,或者是否应该使用 Symfony\Component\HttpFoundation\File\UploadedFile
来提供用于 REST 操作的测试文件。
这就是我在整理这个测试方面的大致情况。 (为简化起见,删除了一些不相关的部分)
public function testCreateMediaObject(): void {
$file = new UploadedFile('fixtures/files/logo.png', 'logo.png');
$client = self::createClient();
$gql = <<<GQL
mutation UploadMediaObject($file: Upload!) {
uploadMediaObject(input: {file: $file}) {
mediaObject {
id
contentUrl
}
}
}
GQL;
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => null],
'map' => ['0' => ['variables.file']],
'0' => $file,
]
]);
dd($response);
}
我收到的回复似乎表明文件没有按预期包含在内。像...
Variable "$file" of non-null type "Upload!" must not be null.
或者.. 如果我尝试通过直接在 variables
属性...
$response = $client->request('POST', '/api/graphql', [
'headers' => ['Content-Type' => 'application/json'],
'json' => [
'query' => $gql,
'variables' => ["file" => $file],
]
]);
然后...
Variable "$file" got invalid value []; Expected type Upload; Could not get uploaded file, be sure to conform to GraphQL multipart request specification. Instead got: []
在我最近的尝试中,我在筛选 graphql 代码后做了很多改动...
$formFields = [
'operations' => '{ "query": "mutation ($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => "{'0': ['variables.file']}",
'0' => DataPart::fromPath(__DIR__.'/../../fixtures/files/logo.png'),
];
$formData = new FormDataPart($formFields);
$response = $client->request('POST', '/api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'body' => $formData->bodyToString(),
]);
最后一次尝试的问题是服务器没有看到任何正文参数。所以我收到异常
'GraphQL multipart request does not respect the specification.'
在 parseMultipartRequest
方法中的 /api-platform/core/src/GraphQl/Action/EntrypointAction.php
中找到。
经过几个小时的调试,我找到了这个解决方案:
$formData = new FormDataPart();
$file = new UploadedFile('src/DataFixtures/files/test.txt', 'test.txt');
$response = $this->$client->request('POST', 'api/graphql', [
'headers' => $formData->getPreparedHeaders()->toArray(),
'extra' => [
'parameters' => [
'operations' => '{ "query": "mutation UploadMediaObject($file: Upload!) { uploadMediaObject(input: {file: $file}) { mediaObject { id contentUrl } } }", "variables": { "file": null } }',
'map' => '{ "0": ["variables.file"] }',
'0' => @$file,
],
'files' => [
$file,
],
],
]);
参考: