web-dev-qa-db-ja.com

MockMVCを介したフォーム投稿のテスト

APIへの一般的なフォームポストができることを確認するためのテストを書いています。

デバッグもかなり追加しましたが、データが実際のフォームによって投稿されていることに気付きました。 (Postman/AngularJSまたはw/e)次のようなmockMVCテストの実行とは異なります。

MvcResult response = mockMvc
            .perform(post("/some/super/secret/url") //
                    .param("someparam1", "somevalue") //
                    .param("someparam2", "somevalue") //                
                    .contentType(MediaType.APPLICATION_FORM_URLENCODED) //
                    .accept(MediaType.APPLICATION_JSON)) //
            .andExpect(status().isOk()) //
            .andReturn();

構成は、実稼働で実行されている構成などとまったく同じです。ただし、インターセプターがコンテンツをログに記録するとき、実際のテスト(mockMVCではありません)では、コンテンツは「someparam1 = somevalue&etc = encore」のようにフォーマットされます

MockMVCコンテンツを印刷すると、実際にはコンテンツがないように見えますが、リクエストにParamsが含まれているため、GETパラメーターのように追加されていると想定しています。

誰でもこれを適切にテストする方法を知っていますか?サーブレットコンテキストにFormHttpMessageConverterが追加されていても、フォームの投稿がSpringによって解析されていないように思われるため、この問題に遭遇しました。

18
Mathijs Segers

クラスパスにApache HTTPComponents HttpClientがある場合、次のようにできます。

    mockMvc.perform(post("/some/super/secret/url")
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .content(EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
                    new BasicNameValuePair("someparam1", "true"),
                    new BasicNameValuePair("someparam2", "test")
            )))));

HttpClientがない場合は、urlencodedフォームエンティティを構築する単純なヘルパーメソッドを使用して実行できます。

    mockMvc.perform(post("/some/super/secret/url")
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .content(buildUrlEncodedFormEntity(
         "someparam1", "value1", 
         "someparam2", "value2"
    ))));

このヘルパー関数では:

private String buildUrlEncodedFormEntity(String... params) {
    if( (params.length % 2) > 0 ) {
       throw new IllegalArgumentException("Need to give an even number of parameters");
    }
    StringBuilder result = new StringBuilder();
    for (int i=0; i<params.length; i+=2) {
        if( i > 0 ) {
            result.append('&');
        }
        try {
            result.
            append(URLEncoder.encode(params[i], StandardCharsets.UTF_8.name())).
            append('=').
            append(URLEncoder.encode(params[i+1], StandardCharsets.UTF_8.name()));
        }
        catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
    return result.toString();
 }
19
Bastian Voigt

また、作成したこの小さなライブラリ https://github.com/f-lopes/spring-mvc-test-utils/ を使用することもできます。

Pom.xmlに依存関係を追加します。

<dependency>
    <groupId>io.florianlopes</groupId>
    <artifactId>spring-mvc-test-utils</artifactId>
    <version>1.0.1</version>
    <scope>test</scope>
</dependency>

MockMvcで使用します。

mockMvc.perform(MockMvcRequestBuilderUtils.postForm("/users", new AddUserForm("John", "Doe", null, new Address(1, "Street", 5222, "New York"))))
    .andExpect(MockMvcResultMatchers.status().isFound())
    .andExpect(MockMvcResultMatchers.redirectedUrl("/users"))
    .andExpect(MockMvcResultMatchers.flash().attribute("message", "success"));

このライブラリは、フォームオブジェクトに従って、MockMvcリクエストにパラメーターを追加するだけです。

ここに私が書いた詳細なチュートリアルがあります: https://blog.florianlopes.io/tool-for-spring-mockmvcrequestbuilder-forms-tests/

1
Florian Lopes