如何使用 MockMvc 解决 MethodArgumentConversionNotSupportedException?
How to resolve MethodArgumentConversionNotSupportedException with MockMvc?
我正在为接受 MultipartFile
的控制器方法编写单元测试
和一个自定义对象 MessageAttachment
。到目前为止,我可以看到 MultipartFile 是请求的正确格式,但 MessageAttachment 不是。
messageAttachment
的解析抛出服务器端 500 错误 MethodArgumentConversionNotSupportedException
。
在测试中将 MessageAttachment 转换为 MockMultipartFile 似乎是一个问题。这类似于此处显示的示例 -
问题:
如何使用 MockMvc 解决 MethodArgumentConversionNotSupportedException?
正在测试的控制器方法
@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
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());
}
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
对于请求的 application/json
部分,您需要使用 @RequestPart
而不是 @RequestParam
。 @RequestPart
的 javadoc 状态
Supported method argument types include MultipartFile
in conjunction
with Spring's MultipartResolver
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 an HttpMessageConverter
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 registered Converter
or PropertyEditor
while
@RequestPart
relies on HttpMessageConverters
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).
据推测,您没有注册 Converter
,也没有注册 PropertyEditor
来解析该部分的内容,而 JSON 的 HttpMessageConverter
是自动注册的已注册(取决于您的 Spring MVC/Boot 版本)如果您在类路径上有 Jackson。
我正在为接受 MultipartFile
的控制器方法编写单元测试
和一个自定义对象 MessageAttachment
。到目前为止,我可以看到 MultipartFile 是请求的正确格式,但 MessageAttachment 不是。
messageAttachment
的解析抛出服务器端 500 错误 MethodArgumentConversionNotSupportedException
。
在测试中将 MessageAttachment 转换为 MockMultipartFile 似乎是一个问题。这类似于此处显示的示例 -
问题:
如何使用 MockMvc 解决 MethodArgumentConversionNotSupportedException?
正在测试的控制器方法
@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
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());
}
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
对于请求的 application/json
部分,您需要使用 @RequestPart
而不是 @RequestParam
。 @RequestPart
的 javadoc 状态
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).
据推测,您没有注册 Converter
,也没有注册 PropertyEditor
来解析该部分的内容,而 JSON 的 HttpMessageConverter
是自动注册的已注册(取决于您的 Spring MVC/Boot 版本)如果您在类路径上有 Jackson。