MockMVC to test Spring MVC form validation

The Spring MVC Test Framework was incorporated into the Spring Framework in version 3.2. It allows tests to be run against the actual spring configuration and a real DispatcherServlet. This makes it great for testing container level configuration that would be impossible to unit test by simply instantiating one or two classes. As an example, here’s a recipe for testing annotation based bean validation in a Spring Web MVC project.

The source code for this is available from the Spanners project on GitHub. This demo code was added in version 2.4.

Setting up annotation based form validation

Form validation can be configured just by annotating the domain model with JSR-303 validation constraints:

 

When the form is submitted to a Web MVC controller, we can tell Spring to validate the entered data by using the @Valid annotation:

 

The result of any validation failure can be shown in the HTML form using spring-form errors tag.

form validation message

Aside from adding a few annotations to my domain model class and my controller class, I’ve not written a single line of Java code to implement this form validation. So if I want to test it, I’ll need to run my tests against the Spring context.

MockMVC

The MockMVC class allows tests to be run against a real Spring application context without actually having to run the complete application in a Servlet container. It’s fairly straightforward to set up:

In the above code, the MockMvc is setup against the WebApplicationContext as defined in the WebMvcConfig class. It could be set up just as easily against XML based application configuration:

Note though, that we’re starting our test against the real application context, not a stub or an approximation. This means that all the goodies that Spring provides for us (such as request mappings, data binding and of course validation) are available and testable.

Testing controllers

A MockMvc based test will typically perform some action (GET or POST to a URL) and then make assertions on the response. Here’s a typical example of verifying a GET request to a URL mapped to a controller:

If any of the expectations are not met then the test will fail.

Testing validation rules

I can POST the form data to my controller and assert (expect) that validation errors are triggered:

As my test class will repeatedly POST data to the same controller, I can abstract the form submission leaving just the andExpect clauses in my test:

 

 

6 Comments

  • Robert Cameron
    December 16, 2013 - 7:42 pm | Permalink

    Hi Stevie,

    I’ve recently started using MockMVC and have become a big fan. What I’ve noticed however is that the methods of my controller called using MockMVC do not show as covered in my Sonar unit test coverage. Have you encountered this, and do you have any idea what I can do about it?

    Thanks,
    Rob

  • December 31, 2013 - 9:26 pm | Permalink

    Sorry Robert, that’s not a problem I’ve experienced myself. I am running Sonar to get test coverage stats but I can’t tell if my MockMVC tests contribute to coverage as I’m running regular unit tests on my controller classes as well as MockMVC tests as described above.

    In my opinion, the above recipe is good for testing Spring container configuration but not so good for testing the logic in the Controller class. I’d still recommend writing a ‘regular’ unit test for that. The test would simply create an instance of the controller and call the updateSpanner() method. If you download the source code from GitHub (link at the top of the post), you’ll see that AddSpannerControllerTest does just that.

    I appreciate that this does not answer your question but I hope it’s of use to you.

  • Robert Cameron
    January 2, 2014 - 4:06 pm | Permalink

    I currently believe the issue is actually due to the use of PowerMockRunner and not MockMVC.

  • sagar
    February 2, 2016 - 7:29 am | Permalink

    give me spring test mvc war file of tested app….

  • Peter Wasele
    October 18, 2018 - 7:44 am | Permalink

    Great, thank you! Regards from Germany.

  • Leave a Reply

    Your email address will not be published. Required fields are marked *