如何使用 Spring MockMvc 放置多部分/表单数据?
Posted
技术标签:
【中文标题】如何使用 Spring MockMvc 放置多部分/表单数据?【英文标题】:How to PUT multipart/form-data using Spring MockMvc? 【发布时间】:2016-11-29 00:42:39 【问题描述】:我有一个带有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
有一个包本地构造函数。
但我想知道有没有更方便的有什么办法可以做到这一点,可能我错过了一些现有的类或方法吗?
【问题讨论】:
您能否将我的答案标记为已接受的答案?这将有助于保持 *** 的清洁和高效。谢谢! 【参考方案1】:是的,有办法,而且也很简单!
我自己也遇到了同样的问题。虽然我对 Sam Brannen 的回答感到灰心,但似乎 Spring MVC 现在确实支持 PUT 文件上传,因为我可以使用 Postman 简单地执行这样的请求(我使用的是 Spring Boot 1.4.2)。所以,我一直在挖掘,发现唯一的问题是MockMvcRequestBuilders.fileUpload()
返回的MockMultipartHttpServletRequestBuilder
具有硬编码为“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());
像魅力一样工作!
【讨论】:
这应该是问题的解决方案,因为它可以解决提出问题的人的问题 仅供参考 - 在春季 5 中,fileUpload
已弃用,应改用 multipart
。除此之外 - 就像一个魅力:)
使用 java 8 lambda 语法:builder.with(request -> request.setMethod("PUT"); return request; );
PUT
字符串也可以从此常量中检索:HttpMethod.PUT.name()
【参考方案2】:
不幸的是,Spring MVC 测试目前不支持此功能,除了创建您自己的自定义 MockPutMultipartHttpServletRequestBuilder
并从标准实现中复制粘贴代码之外,我没有看到其他解决方法。
不管怎样,Spring MVC 默认也不支持PUT
文件上传请求。 Multipart 解析器经过硬编码,仅接受 POST
文件上传请求——既适用于 Apache Commons,也适用于标准 Servlet API 支持。
如果您还希望 Spring 支持 PUT
请求,请随时在 Spring 的 JIRA 问题跟踪器中发送 open a ticket。
【讨论】:
我找到了一个简单的解决方案!看看我的回答 Spring 现在还支持任何方法,而不仅仅是 POST。见this commit【参考方案3】:为 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)
【讨论】:
【参考方案4】:foo
和 file
都可以通过
尝试重写你的控制器:
@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());
【讨论】:
你好。刚刚尝试这样做,但我不断收到“不支持内容类型'应用程序/json'”以进行 mockMvc 测试。我有一个带有两个 RequestPart 的控制器,其中一个是 POJO,另一个是 MultipartFile。我做错了什么?使用邮递员工作正常!以上是关于如何使用 Spring MockMvc 放置多部分/表单数据?的主要内容,如果未能解决你的问题,请参考以下文章
Spring MockMvc 和异步控制器的 HTTP 状态码
使用 Spring MockMVC 测试 Spring 的 @RequestBody
Spring 的 MockMvc 是用于单元测试还是集成测试?