web-dev-qa-db-ja.com

Spring MockMvcを使用してmultipart / form-dataをPUTする方法

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にはパッケージローカルコンストラクターがあるためです。

でも、もっと便利なところはあるかしら。 これを行う方法はありますか?これを行うためのいくつかの既存のクラスまたはメソッドを見逃している可能性がありますか?

19
Andremoniy

はい、方法があり、それも簡単です!

私も同じ問題に遭遇しました。 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());

魅力的な作品!

37
HammerNL

これは残念ながら現在Spring MVC Testでサポートされていません。独自のカスタムMockPutMultipartHttpServletRequestBuilderを作成し、標準実装からコピーして貼り付けるコード以外の回避策はありません。

価値があるのは、Spring MVCもデフォルトでファイルアップロードのPUTリクエストをサポートしないことです。マルチパートリゾルバーは、ファイルアップロードのPOSTリクエストのみを受け入れるようにハードコーディングされています-Apache Commonsと標準のサーブレットAPIサポートの両方で。

SpringがPUTリクエストをさらにサポートするようにしたい場合は、SpringのJIRA課題トラッカーで チケットを開く を自由にご利用ください。

4
Sam Brannen

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());
0
lalilulelo_1986