我有PUT
方法的控制器方法,它接收多部分/表单数据:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(HttpServletRequest request,
@RequestBody Foo foo,
@RequestParam("foo_icon") MultipartFile file) {
...
}
我希望使用MockMvc
对其进行测试。不幸的是,MockMvcRequestBuilders.fileUpload
基本上创建了MockMultipartHttpServletRequestBuilder
的{{1}}方法实例:
POST
修改
当然我可以 我不能创建我自己的super(HttpMethod.POST, urlTemplate, urlVariables)
实现,比如说
MockHttpServletRequestBuilder
因为public MockPutMultipartHttpServletRequestBuilder(String urlTemplate, Object... urlVariables) {
super(HttpMethod.PUT, urlTemplate, urlVariables);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
具有包本地构造函数。
但我想知道是否更方便有没有办法做到这一点,可能是我错过了一些现有的课程或方法吗?
答案 0 :(得分:32)
是的,有办法,而且也很简单!
我自己遇到了同样的问题。虽然我对Sam Brannen的回答感到沮丧,但现在看来Spring MVC支持PUT文件上传,因为我可以使用Postman(我正在使用Spring Boot 1.4.2)进行这样的请求。所以,我一直在挖掘,发现唯一的问题是MockMultipartHttpServletRequestBuilder
返回的MockMvcRequestBuilders.fileUpload()
将方法硬编码为“POST”。然后我发现了with()
方法......
这让我想出了这个简洁的小技巧,迫使MockMultipartHttpServletRequestBuilder
无论如何都要使用“PUT”方法:
MockMultipartFile file = new MockMultipartFile("data", "dummy.csv",
"text/plain", "Some dataset...".getBytes());
MockMultipartHttpServletRequestBuilder builder =
MockMvcRequestBuilders.fileUpload("/test1/datasets/set1");
builder.with(new RequestPostProcessor() {
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.setMethod("PUT");
return request;
}
});
mvc.perform(builder
.file(file))
.andExpect(status().ok());
像魅力一样!
答案 1 :(得分:4)
目前,Spring MVC测试目前不支持这一点,除了在标准实现中创建自己的自定义MockPutMultipartHttpServletRequestBuilder
和复制粘贴代码之外,我还没有看到解决方法。 / p>
对于它的价值,Spring MVC默认情况下也不支持PUT
文件上传请求。 Multipart解析器经过硬编码,只接受POST
文件上传请求 - 包括Apache Commons和标准Servlet API支持。
如果您希望Spring另外支持PUT
个请求,请随时在Spring的JIRA问题跟踪器中open a ticket。
答案 2 :(得分:0)
您可以同时通过foo
和file
尝试像这样重写控制器:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(
HttpServletRequest request,
@RequestPart Foo foo,
@RequestPart MultipartFile file) {
...
}
测试如下:
MockMultipartFile file = new MockMultipartFile("file", "dummy.csv",
"text/plain", "Some dataset...".getBytes());
// application/json if you pass json as string
MockMultipartFile file2 = new MockMultipartFile("foo", "foo.txt",
"application/json", "Foo data".getBytes());
MockMultipartHttpServletRequestBuilder builder =
MockMvcRequestBuilders.multipart("/test1/datasets/set1");
builder.with(new RequestPostProcessor() {
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.setMethod("PUT");
return request;
}
});
mvc.perform(builder
.file(file)
.file(file2))
.andExpect(status().ok());
答案 3 :(得分:0)
为 Kotlin 翻译 @HammerNl 答案。这对我有用。
val file = File("/path/to/file").readBytes()
val multipartFile = MockMultipartFile("image", "image.jpg", "image/jpg", file)
val postProcess = RequestPostProcessor { it.method = "PUT"; it}
mockMvc.perform(
MockMvcRequestBuilders.multipart("/api/image/$id")
.file(multipartFile)
.with(postProcess))
.andExpect(MockMvcResultMatchers.status().isOk)