测试Multipart多文件上传接口时返回400错误码而非200成功码的问题排查
Let's walk through the key issues causing your 400 response and fix them step by step:
1. Mismatched Multipart File Parameter Name
Your controller method expects a MultipartFile[] parameter named multipartFiles, but in your test you're creating a MockMultipartFile with the name files:
MockMultipartFile filePart1 = new MockMultipartFile("files", "file1.pdf", "multipart/form-data", byteContent);
Spring MVC can't map the uploaded file to the controller parameter because the names don't match. You need to align the name in MockMultipartFile with the controller's parameter name:
MockMultipartFile filePart1 = new MockMultipartFile("multipartFiles", "file1.pdf", "multipart/form-data", byteContent);
2. Invalid Request Body Configuration
Your test code is mixing multiple conflicting ways to send the userName parameter, which corrupts the multipart request structure:
.content(userName) .content("{userName:testUser}") //也尝试过这种方式 .param("userName", "testUser")) //也尝试过这种方式
For multipart/form-data requests, never use .content() to set parameters—this overrides the entire request body with raw content, which breaks the multipart format. All parameters (strings and files) should be added via .param() (for strings) and .file() (for files).
Corrected Test Code
Here's the fixed version of your test case with all issues resolved:
@Test public void testUploadMyFiles() throws Exception { byte[] byteContent = new byte[100]; String userName = "testUser"; // Align file parameter name with controller's expectation MockMultipartFile filePart1 = new MockMultipartFile("multipartFiles", "file1.pdf", "multipart/form-data", byteContent); MultipartFile[] multipartFiles = {filePart1}; when(myService.uploadMyFiles(multipartFiles, userName)).thenReturn(Map.of("file1.pdf", "Success")); MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.multipart("/uploadMyFiles") // Add the multipart file correctly .file(filePart1) // Add string parameter as a form field .param("userName", userName)) .andExpect(status().isOk()) .andReturn(); assertEquals(HttpStatus.OK, ((ResponseEntity<?>) result.getAsyncResult()).getStatusCode()); }
Why This Works
- The file now uses the exact parameter name the controller expects, so Spring can bind it properly.
- We've removed all invalid
.content()calls, preserving the correct multipart request structure. - The
userNameparameter is added as a standard form field via.param(), which matchesmultipart/form-datarequirements.
After making these changes, your debug logs should show the multipart file and userName parameter being parsed correctly, and the response should return 200 OK as expected.
内容的提问来源于stack exchange,提问作者mark

