Multipart/form-dataを受け取るPUT
メソッドを持つコントローラーのメソッドがあります。
@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の回答には落胆しましたが、Postmanを使用してそのようなリクエストを簡単に実行できるため(Spring Boot 1.4.2を使用しているため)、Spring MVCは現在、PUTファイルのアップロードをサポートしているようです。それで、私は掘り続けて、唯一の問題が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().ok());
魅力的な作品!
これは残念ながら現在Spring MVC Testでサポートされていません。独自のカスタムMockPutMultipartHttpServletRequestBuilder
を作成し、標準実装からコピーして貼り付けるコード以外の回避策はありません。
価値があるのは、Spring MVCもデフォルトでファイルアップロードのPUT
リクエストをサポートしないことです。マルチパートリゾルバーは、ファイルアップロードのPOST
リクエストのみを受け入れるようにハードコーディングされています-Apache Commonsと標準のサーブレットAPIサポートの両方で。
SpringがPUT
リクエストをさらにサポートするようにしたい場合は、SpringのJIRA課題トラッカーで チケットを開く を自由にご利用ください。
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());