I have a controller's method with a PUT
method, which receives multipart/form-data:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(HttpServletRequest request,
@RequestBody Foo foo,
@RequestParam("foo_icon") MultipartFile file) {
...
}
and I want to test it using MockMvc
. Unfortunately MockMvcRequestBuilders.fileUpload
creates essentially an instance of MockMultipartHttpServletRequestBuilder
which has a POST
method:
super(HttpMethod.POST, urlTemplate, urlVariables)
EDIT:
Surely I can I can not create my own implementation of MockHttpServletRequestBuilder
, say
public MockPutMultipartHttpServletRequestBuilder(String urlTemplate, Object... urlVariables) {
super(HttpMethod.PUT, urlTemplate, urlVariables);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
because MockHttpServletRequestBuilder
has a package-local constructor.
But I'm wondering is there any more convenient Is any way to do this, may be I missed some existent class or method for doing this?
Yes, there is a way, and it's simple too!
I ran into the same problem myself. Though I was discouraged by Sam Brannen's answer, it appears that Spring MVC nowadays DOES support PUT file uploading as I could simply do such a request using Postman (I'm using Spring Boot 1.4.2). So, I kept digging and found that the only problem is the fact that the MockMultipartHttpServletRequestBuilder
returned by MockMvcRequestBuilders.fileUpload()
has the method hardcoded to "POST". Then I discovered the with()
method...
and that allowed me to come up with this neat little trick to force the MockMultipartHttpServletRequestBuilder
to use the "PUT" method anyway:
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());
Works like a charm!