测试多部分文件上传时获取 400 响应代码而不是 200 代码
Getting 400 response code instead of 200 code when testing multipart files upload
我正在测试端点以上传一组多部分文件以及 String
参数。我收到 400 响应而不是 200 (OK)
。关于为什么我得到 400 response
的任何想法,这表明我的请求对象有问题。但是当我检查请求时,内容类型是正确的。
uploadMyFiles.java 端点
@PostMapping(path = "/uploadMyFiles", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public Map<String, String> uploadMyFiles(MultipartFile[] multipartFiles, String userName) {
//..
return statusMap
}
我的测试用例
@Test
public void testUploadMyFiles() throws Exception {
byte[] byteContent = new byte[100];
String userName ="testUser"
MockMultipartFile filePart1 = new MockMultipartFile("files", "file1.pdf", "multipart/form-data", content);
MultipartFile[] multipartFiles={filePart1}
Object resultMap;
when(myService.uploadMyFiles(multipartFiles,userName)).thenReturn(Map.of("file1.pdf", "Success"));
MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.multipart("/uploadMyFiles")
.content(userName)
.content("{userName:testUser}") //tried with this too
.param("userName", "testUser")) //tried with this too
.andExpect(status().isOk())
.andReturn();
assertEquals(HttpStatus.OK, ((ResponseEntity)result.getAsyncResult()).getStatusCode());
}
调试:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /uploadMyFiles
Parameters = {userName=[testUser]}
Headers = [Content-Type:"multipart/form-data", Content-Length:"23"]
Body = <no character encoding set>
Session Attrs = {}
回应
MockHttpServletResponse:
Status = 400
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
HTTP 400(在 spring-web 中)表示 RequestMapping 仅“部分映射”...
测试这个 Controller/RequestMapping:
@Controller
public class MyController {
private static final Logger LOG = LoggerFactory.getLogger(MyController.class);
@PostMapping(path = "/uploadMyFiles", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public @ResponseBody
Map<String, String> uploadMyFiles(MultipartFile[] multipartFiles, String userName) {
if (multipartFiles == null) {
LOG.warn("multipartFiles is null!");
} else {
LOG.info("{} file{} uploaded.", multipartFiles.length, multipartFiles.length > 1 ? "s" : "");
if (LOG.isDebugEnabled()) {
for (MultipartFile mf : multipartFiles) {
LOG.debug("name: {}, size: {}, contentType: {}", mf.getOriginalFilename(), mf.getSize(), mf.getContentType());
}
}
}
// ...
return Map.of("foo", "bar");
}
}
这将是 MockMvc 测试的大纲(,它命中此控制器):
package com.example; // package of spring-boot-app
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MockMvc;
import java.nio.charset.StandardCharsets;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest
class Q66280300ApplicationTests {
@Autowired
private MockMvc mockMvc;
@Test
public void testUploadMyFiles() throws Exception {
byte[] byteContent1 = "text1".getBytes(StandardCharsets.US_ASCII);
byte[] byteContent2 = "text2".getBytes(StandardCharsets.US_ASCII);
String userName = "testUser";
// IMPORTANT: name = "multipartFiles" (name of the request parameter)
MockMultipartFile filePart1 = new MockMultipartFile("multipartFiles", "file1.txt", "text/plain", byteContent1);
MockMultipartFile filePart2 = new MockMultipartFile("multipartFiles", "file2.txt", "text/plain", byteContent2);
this.mockMvc.perform(
multipart("/uploadMyFiles")
.file(filePart1)
.file(filePart2)
.param("userName", userName)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("{\"foo\":\"bar\"}")));
}
}
并且要找到您的文件(在控制器内、日志记录、null...)至关重要,MockMultipartFile
的名称matches 请求参数的名称。 (在我们的例子中,方法参数的“默认”名称:"multipartFiles"
)
我正在测试端点以上传一组多部分文件以及 String
参数。我收到 400 响应而不是 200 (OK)
。关于为什么我得到 400 response
的任何想法,这表明我的请求对象有问题。但是当我检查请求时,内容类型是正确的。
uploadMyFiles.java 端点
@PostMapping(path = "/uploadMyFiles", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public Map<String, String> uploadMyFiles(MultipartFile[] multipartFiles, String userName) {
//..
return statusMap
}
我的测试用例
@Test
public void testUploadMyFiles() throws Exception {
byte[] byteContent = new byte[100];
String userName ="testUser"
MockMultipartFile filePart1 = new MockMultipartFile("files", "file1.pdf", "multipart/form-data", content);
MultipartFile[] multipartFiles={filePart1}
Object resultMap;
when(myService.uploadMyFiles(multipartFiles,userName)).thenReturn(Map.of("file1.pdf", "Success"));
MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.multipart("/uploadMyFiles")
.content(userName)
.content("{userName:testUser}") //tried with this too
.param("userName", "testUser")) //tried with this too
.andExpect(status().isOk())
.andReturn();
assertEquals(HttpStatus.OK, ((ResponseEntity)result.getAsyncResult()).getStatusCode());
}
调试:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /uploadMyFiles
Parameters = {userName=[testUser]}
Headers = [Content-Type:"multipart/form-data", Content-Length:"23"]
Body = <no character encoding set>
Session Attrs = {}
回应
MockHttpServletResponse:
Status = 400
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
HTTP 400(在 spring-web 中)表示 RequestMapping 仅“部分映射”...
测试这个 Controller/RequestMapping:
@Controller
public class MyController {
private static final Logger LOG = LoggerFactory.getLogger(MyController.class);
@PostMapping(path = "/uploadMyFiles", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public @ResponseBody
Map<String, String> uploadMyFiles(MultipartFile[] multipartFiles, String userName) {
if (multipartFiles == null) {
LOG.warn("multipartFiles is null!");
} else {
LOG.info("{} file{} uploaded.", multipartFiles.length, multipartFiles.length > 1 ? "s" : "");
if (LOG.isDebugEnabled()) {
for (MultipartFile mf : multipartFiles) {
LOG.debug("name: {}, size: {}, contentType: {}", mf.getOriginalFilename(), mf.getSize(), mf.getContentType());
}
}
}
// ...
return Map.of("foo", "bar");
}
}
这将是 MockMvc 测试的大纲(,它命中此控制器):
package com.example; // package of spring-boot-app
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MockMvc;
import java.nio.charset.StandardCharsets;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest
class Q66280300ApplicationTests {
@Autowired
private MockMvc mockMvc;
@Test
public void testUploadMyFiles() throws Exception {
byte[] byteContent1 = "text1".getBytes(StandardCharsets.US_ASCII);
byte[] byteContent2 = "text2".getBytes(StandardCharsets.US_ASCII);
String userName = "testUser";
// IMPORTANT: name = "multipartFiles" (name of the request parameter)
MockMultipartFile filePart1 = new MockMultipartFile("multipartFiles", "file1.txt", "text/plain", byteContent1);
MockMultipartFile filePart2 = new MockMultipartFile("multipartFiles", "file2.txt", "text/plain", byteContent2);
this.mockMvc.perform(
multipart("/uploadMyFiles")
.file(filePart1)
.file(filePart2)
.param("userName", userName)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("{\"foo\":\"bar\"}")));
}
}
并且要找到您的文件(在控制器内、日志记录、null...)至关重要,MockMultipartFile
的名称matches 请求参数的名称。 (在我们的例子中,方法参数的“默认”名称:"multipartFiles"
)