You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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()
    );
    
  • 调整测试方法调用逻辑:
    1. 把原来的postForResource方法替换为支持Multipart的调用方式,把刚才构造的Mock文件作为变量和请求绑定
    2. 调整Mockito打桩逻辑:把when(imageService.findBySimilarImage(...))的参数改成any(Upload.class)即可,不需要和测试传入的文件做严格实例匹配,避免因为对象引用不一致导致mock不生效
    3. 后续的响应断言逻辑和原来保持一致,不需要改动
  • 版本兼容方案:如果用的是低版本Spring GraphQL没有内置Multipart测试支持,可以手动按照Multipart请求规范拼包:第一部分传GraphQL查询和变量映射的JSON,第二部分传二进制文件内容,通过WebTestClient发送即可
  • 踩坑提醒:
    • 别试着把文件路径、文件内容硬塞在GraphQL查询字符串里——Upload标量的解析逻辑只会从Multipart请求的文件部分取值,普通JSON字段传值会直接触发标量解析报错,查半天都找不到原因
    • 集成测试阶段没必要接真实的文件存储服务,只要能把文件对象传递到服务层的mock逻辑就完成测试目标,不用走到真实的图片相似度计算、云存储上传等下游逻辑,能大幅降低测试的环境依赖

内容的提问来源于stack exchange,提问作者Roy Khoury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 11:06:04