Spring / MockMvc:文件和非文件部分的多部分发布请求导致与正确对象类型匹配的问题

问题描述 投票:0回答:1

如果我想要像这样的发布请求定义:

    @PostMapping(path = "/metadata/{id}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    ResponseEntity<Void> test(HttpServletResponse response,//
                              @RequestPart(value = "file") MultipartFile file,
                              @RequestPart(value = "partName") Metadata partName,
                              @PathVariable(name = "id") String artifactId) {
        return null;
    }

(其中元数据是一个简单的 Pojo) 然后使用以下测试:

    @Test
    public void testMetadata() throws Exception {
        mockMvc
                .perform(multipart(HttpMethod.POST, "/metadata/123")
                                 .file("file", "file content".getBytes())
                                 .part(getJsonPart())
                                 .contentType(MediaType.MULTIPART_FORM_DATA_VALUE))
                .andExpect(status().isOk());
    }

    private @NotNull MockPart getJsonPart() throws JsonProcessingException {
        byte[] partContent = new ObjectMapper().writeValueAsBytes(new Metadata("foo"));
        MockPart part = new MockPart("partName", partContent);
        part.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return part;
    }

它不匹配 - 我收到 400 响应而不是 200。我认为它无法反序列化有效负载。

但是,当我将后映射的零件类型从“元数据”更改为“对象”时,它就可以工作(将零件反序列化为地图)。

现在我可能对一些显而易见的事情视而不见,但显然我无法自己解决这个问题。有什么提示吗?只是重申一下:我想要得到的是一个具有正确反序列化“元数据”对象的控制器。


为了完整起见,这里有 2 个完整文件:

class Metadata {

    private String value;

    public Metadata(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

@RestController
public class TestController {

    @PostMapping(path = "/metadata/{id}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    ResponseEntity<Void> test(HttpServletResponse response,//
                              @RequestPart(value = "file") MultipartFile file,
                              @RequestPart(value = "partName") Metadata partName,
                              @PathVariable(name = "id") String artifactId) {
        return null;
    }

    @PostMapping(path = "/object/{id}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    ResponseEntity<Void> test(HttpServletResponse response, @RequestPart(value = "file") MultipartFile file,
                              @RequestPart(value = "partName") Object partName,
                              @PathVariable(name = "id") String artifactId) {
        return null;
    }
}
@WebMvcTest(TestController.class)
public class TestControllerTest {

    @Autowired
    public MockMvc mockMvc;

    @Test
    public void failingTest() throws Exception {
        mockMvc
                .perform(multipart(HttpMethod.POST, "/metadata/123")
                                 .file("file", "file content".getBytes())
                                 .part(getJsonPart())
                                 .contentType(MediaType.MULTIPART_FORM_DATA_VALUE))
                .andExpect(status().isOk());
    }

    @Test
    public void passingTest() throws Exception {
        mockMvc
                .perform(multipart(HttpMethod.POST, "/object/123")
                                 .file("file", "file content".getBytes())
                                 .part(getJsonPart())
                                 .contentType(MediaType.MULTIPART_FORM_DATA_VALUE))
                .andExpect(status().isOk());
    }

    private @NotNull MockPart getJsonPart() throws JsonProcessingException {
        byte[] partContent = new ObjectMapper().writeValueAsBytes(new Metadata("foo"));
        MockPart part = new MockPart("partName", partContent);
        part.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return part;
    }
}
java spring unit-testing spring-test mockmvc
1个回答
0
投票

呃,这太尴尬了...

问题是缺少无参构造函数,导致反序列化失败。但在这种情况下,解串器的错误消息会丢失并且不会出现。

所以,解决方案只是一个空的构造函数

© www.soinside.com 2019 - 2024. All rights reserved.