Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / containers / docker

A Tool for Spring MockMvcRequestBuilder to Post Form Objects Easily

4.00/5 (1 vote)
16 May 2017CPOL2 min read 8.6K  
This is a tool for Spring MockMvcRequestBuilder to post form objects.

Reading Time: 2 minutes

Testing Spring MVC Form Validations Using a Tool for MockMvcRequestBuilder

Spring MVC Test Framework is great to test controllers without even running a Servlet container. However, it’s not always straightforward when dealing with form validation, especially when your forms have a lot of properties. This post will show you how to test your form validations easily using a tool that allows MockMvcRequestBuilder to post an entire form object to a controller.

Validating Forms with @Valid Annotation

A quick recap about JSR-303 support in Spring MVC.

The @Valid annotation tells Spring MVC to trigger validation on the annotated bean once a request is made:

C#
@PostMapping("/add")
public String addUser(@Valid AddUserForm addUserForm, 
    BindingResult bindingResult, RedirectAttributes redirectAttributes) {
    if (bindingResult.hasErrors()) {
        return ADD_USER_VIEW;
    } else {
        // Save new user
        redirectAttributes.addFlashAttribute("flash", "User added");
        return "redirect:" + ADD_USER_URL;
    }
}
C#
public class AddUserForm {

    @NotNull
    @Size(min = 1)
    private List firstNames;

    @NotNull
    @Size(min = 3)
    private String name;

    @NotNull
    private LocalDate birthDate;

    @NotNull
    @Valid
    private Address address;

    @NotNull
    @Size(min = 1)
    private String[] hobbies;

    @NotNull
    private Gender gender;
}

Submitting Form Objects with MockMvc

Although MockMvc is a useful tool, it is not so convenient when dealing with huge forms submission. To test a form containing a lot of fields, you have to map each one to an HTTP parameter like this:

C#
this.mockMvc.perform(MockMvcRequestBuilders.post("url")
 .param("field", "fieldValue")
 .param("field2.nestedField", "nestedFieldValue")

This method can be used if the form doesn’t contain too many fields (or nested ones!). However, it makes things more complicated as it’s error prone (field name, missing field, etc.). It’s also repetitive if you have multiples forms validations to test.

This is why I built a tool for MockMVCRequestBuilder (https://github.com/f-lopes/spring-mvc-test-utils).

Note: A better approach would be to reduce the number of fields in your form. If you can’t do it for some reason, you could still use this tool.

Sending Form Objects Using a Custom MockMvcRequestBuilder

This tool allows to send an entire form object using MockMvcRequestBuilder.

The usage is straightforward:

C#
final AddUserForm addUserForm = new AddUserForm
(Arrays.asList("John", "Jack"), 
"Doe", LocalDate.now(), new Address(1, "Amber", "New York"));
this.mockMvc.perform(MockMvcRequestBuilderUtils.postForm("/users/add", addUserForm))
.andExpect(MockMvcResultMatchers.model().attributeErrorCount("addUserForm", 1));

This builder finds fields using reflection and passes them to the request as HTTP parameters:

C#
firstNames[0]=John
firstNames[1]=Jack
lastName=Doe
address.streetNumber=1
address.street=Amber
address.city=New York

It also supports property editors to format the fields the way you want:

C#
MockMvcRequestBuilderUtils.registerPropertyEditor
(LocalDate.class, new CustomLocalDatePropertyEditor("dd/mm/yyyy");

Get the Tool

Add these lines to your pom.xml:

C#
<dependency>
    <groupId>io.florianlopes</groupId>
    <artifactId>spring-mvc-test-utils</artifactId>
    <version>1.0.0</version>
</dependency>

See the documentation for more information: https://github.com/f-lopes/spring-mvc-test-utils.

The example code for this post is available at https://github.com/f-lopes/spring-mvc-form-validation-tests.

The post A tool for Spring MockMvcRequestBuilder to post form objects easily appeared first on Florian Lopes's blog, running in a Docker container..

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)