如何使用 API 平台对 GraphQL 文件上传进行单元测试?

Posted

技术标签:

【中文标题】如何使用 API 平台对 GraphQL 文件上传进行单元测试?【英文标题】:How can I Unit Test GraphQL file Upload with API Platform? 【发布时间】:2021-09-18 02:34:23 【问题描述】:

除了针对我的 GraphQL API 平台后端的其他测试之外,我还尝试测试文件上传。我不太确定 ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Client 类是否有能力促进这个测试,或者是否应该使用 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 中找到。

【问题讨论】:

github.com/jaydenseric/graphql-multipart-request-spec 谢谢,我已经查阅了这个规范,并且能够使用 cURL 等成功使用媒体上传功能。问题更多的是关于如何在功能测试中使用提供的 @ 987654333@. 用 curl 完成...那你应该知道哪里出了问题... content-type, formData 等 感谢信任投票! ;) 所以在第一个场景中你有["file" =&gt; null],在第二个场景中你有一些不同的东西(但没有显示代码),对吧?也许您应该在问题中使用["file" =&gt; null] 让您在第二种情况下所做的事情可见。 【参考方案1】:

经过几个小时的调试,我找到了这个解决方案:

$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,
        ],
    ],
]);

参考:

https://github.com/jaydenseric/graphql-multipart-request-spec https://api-platform.com/docs/core/graphql/

【讨论】:

你成功了@Dario!谢谢!

以上是关于如何使用 API 平台对 GraphQL 文件上传进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法通过邮递员将文件上传到 GraphQL API?

使用 nextjs 应用程序中的 axios 将文件上传到 graphql api 服务器时我错在哪里?

API 平台 GraphQL 关系中的安全性

如何在 hasura graphql 引擎上上传文件或图像

如何使用 axios 将文件上传到使用 graphql-upload 实现的 graphql 后端?

使用 Relay 和 graphql-dotnet 上传文件