Testing Form posts through MockMVC

前端 未结 3 899
悲&欢浪女
悲&欢浪女 2020-12-30 21:11

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 for

相关标签:
3条回答
  • 2020-12-30 21:45

    Here is a Kotlin SpringBoot example:

    @RunWith(MockitoJUnitRunner::class)
    class ApiFormControllerTest {
    
      lateinit var mvc: MockMvc
    
      @InjectMocks
      lateinit var apiFormController: ApiFormController
    
      @Before
      fun setup() {
        mvc = MockMvcBuilders.standaloneSetup(apiFormController).setControllerAdvice(ExceptionAdvice()).build()
      }
    
      fun MockHttpServletRequestBuilder.withForm(params: Map<String, String>): MockHttpServletRequestBuilder {
        this.contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .content(
                EntityUtils.toString(
                    UrlEncodedFormEntity(
                        params.entries.toList().map { BasicNameValuePair(it.key, it.value) }
                    )
                )
            )
        return this
      }
    
      @Test
      fun canSubmitValidForm() {
        mvc.perform(post("/forms").withForm(mapOf("subject" to "hello")))
            .andExpect(status().isOk)
      }
    
    }
    
    0 讨论(0)
  • 2020-12-30 21:54

    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();
     }
    
    0 讨论(0)
  • 2020-12-30 21:59

    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/

    0 讨论(0)
提交回复
热议问题