Affects: 5.3.3
After the update to version 5.3.3 a few of my MockMvc tests failed. After hours of debuging I found out that it is related to #26261. In my test I do the following.
mvc.multipart(POSTS_ME) {
part(mockMultipartJson("video_attributes", payload))
file(mockMultipartFile("video", "sample_video.mp4", "video/mp4", video))
}
protected fun mockMultipartFile(name: String, file: String, type: String, resource: Resource) =
MockMultipartFile(name, file, type, resource.inputStream)
protected fun mockMultipartJson(partName: String, payload: Map<String, Any?>) =
MockPart(partName, JSONObject(payload).toString().encodeToByteArray()).apply {
headers.contentType = MediaType.APPLICATION_JSON
}
Using Postman everything works as expected. I found out my Part file is not getting set as request parameter inside the MockHttpRequest. My Controller has the following methods:
@PostMapping(consumes = [MediaType.MULTIPART_FORM_DATA_VALUE], params = ["image_attributes"])
fun createImagePost(
@RequestPart("image") image: MultipartFile,
@Valid @RequestPart("image_attributes") attributes: CreatePostWithContentCommand,
request: HttpServletRequest
): ResponseEntity<PostDto>
@PostMapping(consumes = [MediaType.MULTIPART_FORM_DATA_VALUE], params = ["video_attributes"])
fun createVideoPost(
@RequestPart("video") video: MultipartFile,
@Valid @RequestPart("video_attributes") attributes: CreatePostWithContentCommand,
request: HttpServletRequest
): ResponseEntity<PostDto>
My Controller decides based on the Request-Paramter which method to call. The methods do various different things with the underlying image / video file. In the MockMultipartHttpServletRequestBuilder class of version 5.3.3 is now an additional check if the Content-Type of my Part file (video_attributes) is compatible to 'text/html', which it is not. Because of that method toParameterValue()
my Parts name is not added to the parameter collection anymore. As I said, with Postman everything works.
Can you please elaborate on that for me? Is there a way to make the test work again? I would rather not change my endpoint just to get the test working, especially by dividing the endpoint or using an additional query parameter this makes my API less efficient.
Thanks in advance, looking forward to your response.
Comment From: rstoyanchev
In the MockMultipartHttpServletRequestBuilder class of version 5.3.3 is now an additional check if the Content-Type of my Part file (video_attributes) is compatible to 'text/html'
It's checking for compatibility with "text/plain" because the part will be represented as a request parameter which needs to be converted as a String. Not all content types make sense to be converted to String but I guess that check is too restrictive.
At runtime we rely on the Servlet container to return request parameter values for parts. Taking some inspiration from Jetty I guess we can simply turn the content to a String.
Comment From: rstoyanchev
@codeMoney095 thanks for the report. There is now a fix in the master branch. If you are able to verify with 5.3.4-SNAPSHOT please do!
Comment From: cmdjulian
Thank you for the fast and professional response. Yes I can confirm its working.