繁体   English   中英

如何使用 Spring MockMvc 放置多部分/表单数据?

[英]How to PUT multipart/form-data using Spring MockMvc?

我有一个带有PUT方法的控制器方法,它接收 multipart/form-data:

   @RequestMapping(value = "/putIn", method = RequestMethod.PUT)
   public Foo updateFoo(HttpServletRequest request,
                           @RequestBody Foo foo,
                           @RequestParam("foo_icon") MultipartFile file) {
    ...
   }

我想使用MockMvc测试它。 不幸的是MockMvcRequestBuilders.fileUpload本质上创建了一个MockMultipartHttpServletRequestBuilder实例,它有一个POST方法:

super(HttpMethod.POST, urlTemplate, urlVariables)

编辑: 当然我 不能创建我自己的MockHttpServletRequestBuilder实现,说

public MockPutMultipartHttpServletRequestBuilder(String urlTemplate, Object... urlVariables) {
    super(HttpMethod.PUT, urlTemplate, urlVariables);
    super.contentType(MediaType.MULTIPART_FORM_DATA);
}

因为MockHttpServletRequestBuilder有一个包本地构造函数。

但我想知道有没有更方便的 方法可以做到这一点,可能我错过了一些现有的类或方法吗?

是的,有办法,而且也很简单!

我自己也遇到了同样的问题。 尽管我对 Sam Brannen 的回答感到气馁,但现在 Spring MVC 似乎确实支持 PUT 文件上传,因为我可以使用 Postman 简单地执行这样的请求(我使用的是 Spring Boot 1.4.2)。 所以,我不停地挖,发现唯一的问题是,事实MockMultipartHttpServletRequestBuilder返回由MockMvcRequestBuilders.fileUpload()已硬编码为“POST”的方法。 然后我发现了with()方法......

这让我想出了这个巧妙的小技巧来强制MockMultipartHttpServletRequestBuilder都使用“PUT”方法:

    MockMultipartFile file = new MockMultipartFile("data", "dummy.csv",
            "text/plain", "Some dataset...".getBytes());

    MockMultipartHttpServletRequestBuilder builder =
            MockMvcRequestBuilders.fileUpload("/test1/datasets/set1");
    builder.with(new RequestPostProcessor() {
        @Override
        public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
            request.setMethod("PUT");
            return request;
        }
    });
    mvc.perform(builder
            .file(file))
            .andExpect(status().isOk());

奇迹般有效!

不幸的是,Spring MVC 测试目前不支持此功能,除了创建您自己的自定义MockPutMultipartHttpServletRequestBuilder和从标准实现复制粘贴代码之外,我没有看到其他解决方法。

值得一提的是,Spring MVC 默认也不支持文件上传的PUT请求。 Multipart 解析器被硬编码为只接受文件上传的POST请求——无论是对于 Apache Commons 还是标准 Servlet API 支持。

如果您还希望 Spring 支持PUT请求,请随时在 Spring 的 JIRA 问题跟踪器中开一张票

您可以同时传递foofile

尝试重写您的控制器,如:

@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(
    HttpServletRequest request,
    @RequestPart Foo foo,
    @RequestPart MultipartFile file) {
    ...
}

测试看起来像:

    MockMultipartFile file = new MockMultipartFile("file", "dummy.csv",
            "text/plain", "Some dataset...".getBytes());
    // application/json if you pass json as string
    MockMultipartFile file2 = new MockMultipartFile("foo", "foo.txt",
            "application/json", "Foo data".getBytes());

    MockMultipartHttpServletRequestBuilder builder =
            MockMvcRequestBuilders.multipart("/test1/datasets/set1");
    builder.with(new RequestPostProcessor() {
        @Override
        public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
            request.setMethod("PUT");
            return request;
        }
    });
    mvc.perform(builder
            .file(file)
            .file(file2))
            .andExpect(status().ok());

为 Kotlin 翻译 @HammerNl 答案。 这对我有用。

val file = File("/path/to/file").readBytes()
val multipartFile = MockMultipartFile("image", "image.jpg", "image/jpg", file)

val postProcess = RequestPostProcessor { it.method = "PUT"; it}
mockMvc.perform(
    MockMvcRequestBuilders.multipart("/api/image/$id")
        .file(multipartFile)
        .with(postProcess))
        .andExpect(MockMvcResultMatchers.status().isOk)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM