如何使用MockMvc解决MethodArgumentConversionNotSupportedException?

时间:2018-06-20 16:41:24

标签: spring-mvc mockito multipartform-data mockmvc

我正在为接受MultipartFile的控制器方法编写单元测试 和自定义对象MessageAttachment。到目前为止,我可以看到MultipartFile是请求的正确格式,但MessageAttachment不是。

messageAttachment的解析引发了MethodArgumentConversionNotSupportedException的服务器端500错误。

在测试中将MessageAttachment转换为MockMultipartFile似乎是一个问题。这类似于此处显示的示例-https://stackoverflow.com/a/21805186

问题:

如何使用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                                                                                                                                                                                                                        

1 个答案:

答案 0 :(得分:-1)

对于部分@RequestPart,您需要使用@RequestParam而不是application/json@RequestPart状态的Javadoc

  

受支持的方法参数类型包括MultipartFile   借助Spring的MultipartResolver抽象,   javax.servlet.http.Part结合Servlet 3.0多部分   请求或其他任何方法参数的内容   该部分通过HttpMessageConverter传递给   请考虑请求部分的“ Content-Type”标头。这是   类似于@RequestBody为解决基于   非分段常规请求的内容。

     

请注意,@RequestParam批注也可以用于关联   带有方法参数的“ multipart / form-data”请求的一部分   支持相同的方法参数类型。 主要区别在于   当方法参数不是字符串时,@RequestParam依赖于类型   通过注册的ConverterPropertyEditor进行转换   @RequestPart依靠HttpMessageConverters的考虑   请求部分的“内容类型”标头。 @RequestParam   与@RequestPart一起用于名称-值表单字段   可以与包含更复杂内容(例如JSON,XML)的部分一起使用。

大概您没有注册ConverterPropertyEditor来解析该部分的内容,而JSON的HttpMessageConverter会自动注册(取决于您的Spring) MVC /引导版本)(如果您在类路径中有Jackson)。