Как разрешить исключение MethodArgumentConversionNotSupportedException с MockMvc?
Я пишу модульный тест для метода контроллера, который принимает MultipartFile
и пользовательский объект MessageAttachment
, До сих пор я вижу, что MultipartFile является правильным форматом для запроса, а MessageAttachment - нет.
Разбор messageAttachment
выдает ошибку 500 на стороне сервера с MethodArgumentConversionNotSupportedException
,
Кажется, что проблема с преобразованием MessageAttachment в MockMultipartFile в тесте. Это похоже на пример, показанный здесь - /questions/15590653/ispolzovanie-spring-mvc-test-dlya-modulnogo-testirovaniya-mnogochastnogo-post-zaprosa/15590659#15590659
Вопрос:
Как вы можете разрешить исключение MethodArgumentConversionNotSupportedException с 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
1 ответ
Вы хотите использовать @RequestPart
вместо @RequestParam
для части запроса, которая application/json
, Javadoc для @RequestPart
состояния
Поддерживаемые типы аргументов метода включают
MultipartFile
в сочетании с весныMultipartResolver
абстракция,javax.servlet.http.Part
в сочетании с многочастными запросами Servlet 3.0 или иным образом для любого другого аргумента метода, содержимое части передается черезHttpMessageConverter
принимая во внимание заголовок "Content-Type" части запроса. Это аналогично тому, что@RequestBody
позволяет разрешить аргумент, основанный на содержимом регулярного запроса, не состоящего из нескольких частей.Обратите внимание, что
@RequestParam
аннотацию также можно использовать для связывания части запроса "multipart / form-data" с аргументом метода, поддерживающим те же типы аргументов метода. Основное отличие состоит в том, что когда аргумент метода не является строкой,@RequestParam
полагается на преобразование типа через зарегистрированныйConverter
или жеPropertyEditor
в то время как@RequestPart
опирается наHttpMessageConverters
принимая во внимание заголовок "Content-Type" части запроса.@RequestParam
скорее всего будет использоваться с полями формы имя-значение, в то время как@RequestPart
скорее всего будет использоваться с частями, содержащими более сложный контент (например, JSON, XML).
Предположительно, вы не зарегистрировали Converter
ни PropertyEditor
для анализа содержимого этой части, тогда как HttpMessageConverter
для JSON автоматически регистрируется (в зависимости от вашей версии Spring MVC/Boot), если у вас есть Джексон на пути к классам.