如何测试接收POJO与MultipartFile数组的POST接口?
MockMVC测试Multipart接口遇到400错误的解决方法
我是MockMVC新手,已经成功编写部分基础测试,但在测试一个需携带POJO和MultipartFile数组两个参数的POST接口时遇到瓶颈——请求无法到达服务层,始终返回400 Bad Request错误。
我的测试代码
@Test public void vytvorPodnetTest() throws Exception { var somePojo = new SomePojo(); somePojo.setSomeVariable("test_value"); var roles = List.of("TEST_USER"); var uid = "00000000-0000-0000-0000-000000000001"; MockMultipartFile[] attachments = {new MockMultipartFile("file1.txt", "file1.txt", "text/plain", "file1 content".getBytes()), new MockMultipartFile("file2.txt", "file2.txt", "text/plain", "file2 content".getBytes())}; MockMultipartHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart("/some-pojo/create"); builder.with(req -> { req.setMethod("POST"); return req; }); MvcResult result = mockMvc.perform(builder.file(attachments[0]).file(attachments[1]) .param("SomePojo", new ObjectMapper().writeValueAsString(somePojo)) .file(attachment[0]) .with(TestUtils.generateJWTToken(uid, roles))) .andExpect(status.isOk()) .andReturn(); }
控制器方法
@PostMapping(value = "/create", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}) public UUID createPojo( @RequestPart(value = "SomePojo") SomePojo somePojo, @RequestPart(value = "attachments", required = false) MultipartFile[] attachments) { return pojoService.create(somePojo, attachments); }
问题分析与修正方案
核心问题点
- POJO参数传递方式错误:控制器用
@RequestPart接收POJO,测试中却用.param()传递,这是普通表单字段的传递方式,无法被@RequestPart解析。 - 文件参数命名不匹配:控制器中文件数组的参数名是
attachments,但测试创建MockMultipartFile时未指定该参数名,Spring无法将文件绑定到数组。 - 重复添加文件:测试代码中重复调用了
.file(attachments[0]),导致请求中存在重复的文件part。 - 多余的请求方法设置:
MockMvcRequestBuilders.multipart()默认就是POST请求,无需手动设置。
修正后的测试代码
@Test public void vytvorPodnetTest() throws Exception { var somePojo = new SomePojo(); somePojo.setSomeVariable("test_value"); ObjectMapper objectMapper = new ObjectMapper(); String pojoJson = objectMapper.writeValueAsString(somePojo); var roles = List.of("TEST_USER"); var uid = "00000000-0000-0000-0000-000000000001"; // 第一个参数是请求参数名,需和控制器的@RequestPart("attachments")匹配 MockMultipartFile[] attachments = { new MockMultipartFile("attachments", "file1.txt", "text/plain", "file1 content".getBytes()), new MockMultipartFile("attachments", "file2.txt", "text/plain", "file2 content".getBytes()) }; MockMultipartHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart("/some-pojo/create"); // 用.part()传递POJO,指定媒体类型为application/json builder.part(new MockPart("SomePojo", pojoJson.getBytes(StandardCharsets.UTF_8))) .file(attachments[0]) .file(attachments[1]) .with(TestUtils.generateJWTToken(uid, roles)); MvcResult result = mockMvc.perform(builder) .andExpect(status.isOk()) .andReturn(); }
也可以用.requestPart()方法简化POJO传递:
// 替换builder.part(...)这一行 builder.requestPart("SomePojo", objectMapper.writeValueAsBytes(somePojo)) .contentType(MediaType.APPLICATION_JSON)
内容的提问来源于stack exchange,提问作者Wired5149
相关产品推荐
相关产品推荐

