如何在Apollo GraphQL Upload标量查询的JUnit集成测试中传递文件?
带Upload标量的GraphQL接口JUnit集成测试实现方案
当前测试卡点现状
需要为接收Apollo文件上传(Upload标量)的GraphQL查询编写集成测试,目前常规的GraphQL测试模板调用方式无法处理文件类参数,现有代码逻辑如下:
现有测试代码
@Test void imageFromSimilarImage() throws IOException { when(imageService.findBySimilarImage(/*** some-file ***/)).thenReturn(TEST_IMAGE_LIST); GraphQLResponse response = graphQLTestTemplate.postForResource("graphql/image-from-similar-image.graphql"); assertThat(response.isOk()).isTrue(); assertThat(response.getList("$.data.imageFromSimilarImage", Image.class)).contains(TEST_IMAGE_A); }
现有GraphQL请求文件内容
存放在resources/graphql/image-from-similar-image.graphql的测试请求目前因为参数占位问题无法运行:
query { imageFromSimilarImage(file: /*** "some-file-content" ***/) { url cloudinaryId tags { value } } }
项目现有GraphQL Schema核心定义
image.graphql中对Upload标量和查询接口的定义:
scalar Upload schema { query: Query mutation: Mutation } type Image { id: ID! cloudinaryId: String! url: String! tags: [Tag] } type Tag { id: ID! value: String! image: Image! } type Query { imageFromTag(tags : [String!]!): [Image] imageFromSimilarImage(file: Upload!): [Image] allImages : [Image] } type Mutation { createImage(files: [Upload!]!) : [Image] }
可落地实现思路
核心要记住:Upload标量不能通过普通JSON格式的GraphQL请求传递,必须按照GraphQL Multipart请求规范,把查询文本和二进制文件拆成独立的Multipart部分发送,不能硬把文件内容塞在查询字符串的占位符里。
具体步骤:
- 版本适配确认:如果用的是Spring GraphQL 1.1+版本,自带的
graphQLTestTemplate已经内置了Multipart文件上传的测试支持,不需要额外引入第三方工具 - 改造GraphQL测试请求文件:把文件参数改成变量引用,替换原来的硬编码占位符:
query ImageFromSimilarImage($file: Upload!) { imageFromSimilarImage(file: $file) { url cloudinaryId tags { value } } } - 构造测试用Mock文件:用Spring自带的
MockMultipartFile在内存里创建测试图片对象,不需要依赖本地磁盘文件,示例:MockMultipartFile testFile = new MockMultipartFile( "file", "test-image.jpg", MediaType.IMAGE_JPEG_VALUE, "test-image-content".getBytes() ); - 调整测试方法调用逻辑:
- 把原来的
postForResource方法替换为支持Multipart的调用方式,把刚才构造的Mock文件作为变量和请求绑定 - 调整Mockito打桩逻辑:把
when(imageService.findBySimilarImage(...))的参数改成any(Upload.class)即可,不需要和测试传入的文件做严格实例匹配,避免因为对象引用不一致导致mock不生效 - 后续的响应断言逻辑和原来保持一致,不需要改动
- 把原来的
- 版本兼容方案:如果用的是低版本Spring GraphQL没有内置Multipart测试支持,可以手动按照Multipart请求规范拼包:第一部分传GraphQL查询和变量映射的JSON,第二部分传二进制文件内容,通过WebTestClient发送即可
- 踩坑提醒:
- 别试着把文件路径、文件内容硬塞在GraphQL查询字符串里——Upload标量的解析逻辑只会从Multipart请求的文件部分取值,普通JSON字段传值会直接触发标量解析报错,查半天都找不到原因
- 集成测试阶段没必要接真实的文件存储服务,只要能把文件对象传递到服务层的mock逻辑就完成测试目标,不用走到真实的图片相似度计算、云存储上传等下游逻辑,能大幅降低测试的环境依赖
内容的提问来源于stack exchange,提问作者Roy Khoury
相关产品推荐
相关产品推荐

