1. 概述

本文将手把手带你用 MockMvc 实现对 Spring 中 Multipart POST 接口的测试。这类接口常见于文件上传场景,测试时需要模拟带文件的表单提交,稍有不慎就容易踩坑。掌握正确的姿势,能让你的单元测试简单粗暴又可靠。

2. Maven 依赖

测试前,确保你的 pom.xml 引入了必要的依赖。核心是 JUnit 和 Spring Test:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.16.RELEASE</version>
    <scope>test</scope>
</dependency>

✅ 这两个依赖是基石,缺一不可。如果你用的是 Spring Boot,通常 spring-boot-starter-test 已经帮你打包好了。

3. 测试 Multipart POST 接口

3.1 接口定义

先看一个典型的文件上传接口:

@PostMapping(path = "/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
    return file.isEmpty() ?
      new ResponseEntity<String>(HttpStatus.NOT_FOUND) : new ResponseEntity<String>(HttpStatus.OK);
}

这个接口干了两件事:

  • 接收名为 file 的文件参数。
  • 如果文件非空,返回 200 OK;否则返回 404 NOT FOUND。

3.2 编写测试

接下来是重头戏——如何用 MockMvc 模拟这个上传请求。

步骤一:注入上下文

测试类中,先自动注入 WebApplicationContext,它是构建 MockMvc 的原材料:

@Autowired
private WebApplicationContext webApplicationContext;

步骤二:构造测试用例

@Test
public void whenFileUploaded_thenVerifyStatus() 
  throws Exception {
    MockMultipartFile file 
      = new MockMultipartFile(
        "file",                           // 参数名,必须和 @RequestParam 一致
        "hello.txt",                      // 原始文件名
        MediaType.TEXT_PLAIN_VALUE,       // 内容类型
        "Hello, World!".getBytes()        // 文件内容
      );

    MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    
    mockMvc.perform(multipart("/upload").file(file))
      .andExpect(status().isOk());
}

关键点解析:

  • ✅ **MockMultipartFile**:用来模拟一个上传的文件。构造函数的四个参数缺一不可,尤其是第一个参数 file,必须和接口的 @RequestParam("file") 完全匹配。
  • ✅ **MockMvcBuilders.webAppContextSetup()**:基于 Spring 容器上下文构建一个接近真实环境的测试 MockMvc
  • ✅ **multipart("/upload").file(file)**:这是精髓。multipart() 方法明确告诉 MockMvc 这是一个 multipart 请求,并通过 .file() 添加文件。
  • ✅ **.andExpect(status().isOk())**:断言返回状态码为 200,验证业务逻辑正确。

⚠️ 踩坑提醒:

  • 如果你用 post("/upload") 而不是 multipart(),请求体格式不对,测试会失败。
  • 文件参数名("file")必须和接口定义严格一致,否则后端收不到文件,file.isEmpty() 会返回 true,导致断言失败。

4. 总结

本文通过一个简单例子,展示了如何使用 MockMvcMockMultipartFile 对 Spring 的 Multipart POST 接口进行有效测试。

核心就三点:

  1. MockMultipartFile 构造虚拟文件。
  2. multipart() 而不是 post() 发起请求。
  3. 确保参数名、路径完全匹配。

这套方法简单直接,能覆盖绝大多数文件上传测试场景。

完整代码示例已托管至 GitHub: https://github.com/yourname/spring-tutorials/tree/master/spring-mvc-java-2


原始标题:Testing a Spring Multipart POST Request