如何使用MockMvc解决MethodArgumentConversionNotSupportedException? [英] How to resolve MethodArgumentConversionNotSupportedException with MockMvc?

查看:695
本文介绍了如何使用MockMvc解决MethodArgumentConversionNotSupportedException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

messageAttachment的解析会引发MethodArgumentConversionNotSupportedException的服务器端500错误.

The parsing of the messageAttachment throws a server side 500 error with MethodArgumentConversionNotSupportedException.

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

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

问题:

如何使用MockMvc解决MethodArgumentConversionNotSupportedException?

How can you resolve a MethodArgumentConversionNotSupportedException with MockMvc?

正在测试的控制器方法

 @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

You'll want to use @RequestPart instead of @RequestParam for the part of the request that is application/json. The javadoc for @RequestPart states

受支持的方法参数类型一起包括MultipartFile 使用Spring的MultipartResolver抽象, javax.servlet.http.Part与Servlet 3.0 multipart一起使用 请求或其他任何方法参数的内容 该零件通过HttpMessageConverter传递给 请考虑请求部分的"Content-Type"标头.这是 类似于@RequestBody所做的基于 非分段常规请求的内容.

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.

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

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).

大概您没有注册ConverterPropertyEditor来解析该部分的内容,而如果JSON HttpMessageConverter会自动注册(取决于您的Spring MVC/Boot版本),如果你在课程路径上有杰克逊.

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.

这篇关于如何使用MockMvc解决MethodArgumentConversionNotSupportedException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆