问题
I'm writing a unit test for a controller method that accepts a MultipartFile
and a custom object MessageAttachment
. So far I can see that the MultipartFile is the correct format for the request but the MessageAttachment is not.
The parsing of the messageAttachment
throws a server side 500 error with MethodArgumentConversionNotSupportedException
.
It seem to be an issue with converting the MessageAttachment to a MockMultipartFile in the test. This is similar to the example shown here - https://stackoverflow.com/a/21805186
Question:
How can you resolve a MethodArgumentConversionNotSupportedException with MockMvc?
Controller method under test
@RequestMapping(value = "/", method = RequestMethod.POST, consumes = "multipart/form-data", produces = "application/json")
public ResponseEntity<MessageAttachment> handleFileUpload(@RequestParam(value = "file", required = true) MultipartFile file, @RequestParam(value = "messageAttachment") MessageAttachment messageAttachment) {
//do stuff with the file and attachment passed in..
MessageAttachment attachment = new MessageAttachment();
return ResponseEntity.accepted().header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + file.getOriginalFilename() + "\"").body(attachment);
}
MockMvc Test
@Test
public void shouldSaveUploadedFile() throws Exception {
// Given
ObjectMapper mapper = new ObjectMapper();
MessageAttachment messageAttachment = new MessageAttachment();
messageAttachment.setTimestamp(new Date());
MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain",
"Spring Framework".getBytes());
//Mapping the msgAttachment to a MockMultipartFile HERE
MockMultipartFile msgAttachment = new MockMultipartFile("messageAttachment", "","application/json",
mapper.writeValueAsString(messageAttachment).getBytes());
// When
this.mockMvc.perform(MockMvcRequestBuilders.multipart("/media/")
.file(multipartFile)
.file(msgAttachment)).andDo(MockMvcResultHandlers.print());
}
Console output of MockMvcResultHandlers.print()
MockHttpServletRequest:
HTTP Method = POST
Request URI = /media/
Parameters = {}
Headers = {Content-Type=[multipart/form-data]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.fizz.buzz.fizzapi.controller.MediaUploadController
Method = public org.springframework.http.ResponseEntity<com.fizz.buzz.fizzapi.model.MessageAttachment> com.fizz.buzz.fizzapi.controller.MediaUploadController.handleFileUpload(org.springframework.web.multipart.Mu
ltipartFile,com.fizz.buzz.fizzapi.model.MessageAttachment,javax.servlet.http.HttpServletRequest)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
回答1:
You'll want to use @RequestPart
instead of @RequestParam
for the part of the request that is application/json
. The javadoc for @RequestPart
states
Supported method argument types include
MultipartFile
in conjunction with Spring'sMultipartResolver
abstraction,javax.servlet.http.Part
in conjunction with Servlet 3.0 multipart requests, or otherwise for any other method argument, the content of the part is passed through anHttpMessageConverter
taking into consideration the 'Content-Type' header of the request part. This is analogous to what@RequestBody
does to resolve an argument based on the content of a non-multipart regular request.Note that
@RequestParam
annotation can also be used to associate the part of a "multipart/form-data" request with a method argument supporting the same method argument types. The main difference is that when the method argument is not a String,@RequestParam
relies on type conversion via a registeredConverter
orPropertyEditor
while@RequestPart
relies onHttpMessageConverters
taking into consideration the 'Content-Type' header of the request part.@RequestParam
is likely to be used with name-value form fields while@RequestPart
is likely to be used with parts containing more complex content (e.g. JSON, XML).
Presumably, you haven't registered a Converter
, nor a PropertyEditor
, to parse the content of that part, whereas an HttpMessageConverter
for JSON is automatically registered (depending on your Spring MVC/Boot version) if you have Jackson on the classpath.
来源:https://stackoverflow.com/questions/50953227/how-to-resolve-methodargumentconversionnotsupportedexception-with-mockmvc