Testing Form posts through MockMVC

早过忘川 提交于 2019-11-29 11:02:14

问题


I'm writing tests to verify that I can do a generic form post to our API.

I've also added quite some debugging, but I noticed that the data posted by an actual form; (Postman / AngularJS or w/e) Differs from doing a mockMVC test like:

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

The config is exactly the same as the config running in production, and such. However When my interceptor logs the content, in real test (not mockMVC) the content is formatted like "someparam1=somevalue&etc=encore"

When I print the mockMVC content I actually seem to have no content, but there are Params in the request, I assume they're added like GET parameters.

Anyone know how to properly test this? I came upon this issue since it seems like our form posts don't seem to be parsed by Spring even though we have the FormHttpMessageConverter added to the servlet context.


回答1:


If you have Apache HTTPComponents HttpClient on your classpath, you can do it like this:

    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")
            )))));

If you don't have HttpClient, you can do it with a simple helper method that constructs the urlencoded form entity:

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

With this helper function:

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();
 }



回答2:


You could also use this small library I created: https://github.com/f-lopes/spring-mvc-test-utils/.

Add dependency in pom.xml:

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

Use it with 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"));

This library simply adds the parameters to the MockMvc request, according to the form object.

Here is a detailed tutorial I wrote: https://blog.florianlopes.io/tool-for-spring-mockmvcrequestbuilder-forms-tests/



来源:https://stackoverflow.com/questions/36568518/testing-form-posts-through-mockmvc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!