如何使用 Spring MockMvc PUT multipart/form-data?
How to PUT multipart/form-data using Spring MockMvc?
我有一个带有 PUT
方法的控制器方法,它接收 multipart/form-data:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(HttpServletRequest request,
@RequestBody Foo foo,
@RequestParam("foo_icon") MultipartFile file) {
...
}
并且我想使用 MockMvc
对其进行测试。不幸的是 MockMvcRequestBuilders.fileUpload
本质上创建了一个 MockMultipartHttpServletRequestBuilder
的实例,它有一个 POST
方法:
super(HttpMethod.POST, urlTemplate, urlVariables)
编辑:
我当然可以 我不能创建我自己的 MockHttpServletRequestBuilder
实现,比如说
public MockPutMultipartHttpServletRequestBuilder(String urlTemplate, Object... urlVariables) {
super(HttpMethod.PUT, urlTemplate, urlVariables);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
因为 MockHttpServletRequestBuilder
有一个包本地构造函数。
但是我想知道有没有更方便的有什么方法可以做到这一点,可能是我错过了一些现有的class或方法吗?
不幸的是,Spring MVC 测试目前不支持此功能,除了创建您自己的自定义 MockPutMultipartHttpServletRequestBuilder
和从标准实施。
就其价值而言,Spring MVC 默认也不支持 PUT
文件上传请求。 Multipart 解析器被硬编码为仅接受 POST
文件上传请求——Apache Commons 和标准 Servlet API 支持。
如果您还希望 Spring 支持 PUT
请求,请随时在 Spring 的 JIRA 问题跟踪器中 open a ticket。
是的,有办法,而且也很简单!
我运行自己也遇到了同样的问题。虽然我对 Sam B运行nen 的回答感到气馁,但现在看来 Spring MVC 确实支持 PUT 文件上传,因为我可以简单地使用 Postman 执行这样的请求(我正在使用 Spring启动 1.4.2)。所以,我继续挖掘,发现唯一的问题是 MockMvcRequestBuilders.fileUpload()
返回的 MockMultipartHttpServletRequestBuilder
的方法硬编码为“POST”。然后我发现了with()
方法...
这让我想出了这个巧妙的小技巧来强制 MockMultipartHttpServletRequestBuilder
使用“PUT”方法:
MockMultipartFile file = new MockMultipartFile("data", "dummy.csv",
"text/plain", "Some dataset...".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))
.andExpect(status().isOk());
很有魅力!
您可以同时传递 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());
翻译@HammerNl 对 Kotlin 的回答。这对我有用。
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)
我有一个带有 PUT
方法的控制器方法,它接收 multipart/form-data:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(HttpServletRequest request,
@RequestBody Foo foo,
@RequestParam("foo_icon") MultipartFile file) {
...
}
并且我想使用 MockMvc
对其进行测试。不幸的是 MockMvcRequestBuilders.fileUpload
本质上创建了一个 MockMultipartHttpServletRequestBuilder
的实例,它有一个 POST
方法:
super(HttpMethod.POST, urlTemplate, urlVariables)
编辑:
我当然可以 我不能创建我自己的 MockHttpServletRequestBuilder
实现,比如说
public MockPutMultipartHttpServletRequestBuilder(String urlTemplate, Object... urlVariables) {
super(HttpMethod.PUT, urlTemplate, urlVariables);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
因为 MockHttpServletRequestBuilder
有一个包本地构造函数。
但是我想知道有没有更方便的有什么方法可以做到这一点,可能是我错过了一些现有的class或方法吗?
不幸的是,Spring MVC 测试目前不支持此功能,除了创建您自己的自定义 MockPutMultipartHttpServletRequestBuilder
和从标准实施。
就其价值而言,Spring MVC 默认也不支持 PUT
文件上传请求。 Multipart 解析器被硬编码为仅接受 POST
文件上传请求——Apache Commons 和标准 Servlet API 支持。
如果您还希望 Spring 支持 PUT
请求,请随时在 Spring 的 JIRA 问题跟踪器中 open a ticket。
是的,有办法,而且也很简单!
我运行自己也遇到了同样的问题。虽然我对 Sam B运行nen 的回答感到气馁,但现在看来 Spring MVC 确实支持 PUT 文件上传,因为我可以简单地使用 Postman 执行这样的请求(我正在使用 Spring启动 1.4.2)。所以,我继续挖掘,发现唯一的问题是 MockMvcRequestBuilders.fileUpload()
返回的 MockMultipartHttpServletRequestBuilder
的方法硬编码为“POST”。然后我发现了with()
方法...
这让我想出了这个巧妙的小技巧来强制 MockMultipartHttpServletRequestBuilder
使用“PUT”方法:
MockMultipartFile file = new MockMultipartFile("data", "dummy.csv",
"text/plain", "Some dataset...".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))
.andExpect(status().isOk());
很有魅力!
您可以同时传递 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());
翻译@HammerNl 对 Kotlin 的回答。这对我有用。
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)