Spring 3.2 Rundown, MVC Testing

Spring 3.2 comes with new, improved support for testing within the Spring MVC domain. The gist of the new MVC test feature, is that you can test your controllers in ways such that requests are routed via a proper MVC infrastructure, i.e. via the DispatcherServlet.
Previously, you may have used various mocks to test the code inside each controller method. With the new functionality, you can also test and verify specifics of the controller method, such as the mapping, HTTP headers, request data, content types and more.

So how would you accomplish this? Let’s start by turning our attention to the spring-test module, and the org.springframework.test.web.servlet package where we find the new MockMvc class. MockMvc acts as an entry point to the MVC structure under test. It’s a tool you can use to simulate requests against your controllers, with support for all kinds of assertions on the results. As indicated above, everything about your controller should work as it would at runtime, including servlet filters, view templates and the like. However, the requests will not be running in an actual servlet container, which means that JSPs will not work properly (although you can still assert some things like what model objects were set).

To get hold of an instance of MockMvc, there’s a convenient builder, namely org.springframerowk.test.web.servlet.setup.MockMvcBuilders. Currently, there are two builders you can instantiate, and they should be used for different purposes.

First, you can create a standalone MockMvc for one or more of your controller objects (annotated with @Controller). A “minimum” infrastructure required by the DispatcherServlet is then created, which may be customized as needed. This option is specifically intended for unit testing one controller at a time, leaving testing of the MVC infrastructure itself, the Web Application Context, to other test classes.

Second, you may create a MockMvc given a particular WebApplicationContext (a class which is also new in 3.2). This allows you to load a full Spring MVC configuration in which the controller under test will exist during tests. This option should be considered for integration tests, where the focus isn’t solely on the controller’s code, but the effective behaviour of the controller in the scope of the tested application.

Now it’s time to look at an example, which will demonstrate a standalone controller test and how to perform assertions. First, a very simple controller:

@Controller
public class BlogController {

    @RequestMapping(value = "/mvc/plaintext", method = RequestMethod.GET, headers = "Accept=text/plain")
    @ResponseBody
    public String plain() {
        return "a response body";
    }

}

And a simple test for this controller:

import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

public class BlogControllerTest {
    @Test
    public void testPlain() throws Exception {
        MockMvcBuilders.standaloneSetup(new BlogController()).build()
                .perform(get("/mvc/plaintext"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().contentType("text/plain"))
                .andExpect(content().string("a response body"));
    }
}

As you can see, MockMvc allows for a fluent-API way of testing the controller, including assertions.

When you call “perform” on MockMvc, the result is a ResultActions, on which you can “expect” a wide variety of criteria via the “andExpect” method. The criteria here, are instances of ResultMatcher, for which there exist a large number of helper classes. For example, MockMvcResultMatchers can be statically imported to support matchers for asserting content, view, model, urls, response status, headers and more!

As we saw, there’s also a static “print” method, used as parameter to “andDo” on the ResultActions object, which will dump the result of the performed request to standard out:

this.mockMvc.perform(......).andDo(print());

Hopefully, this blog is enough to get you going with MVC testing. If you want to go more in depth in this topic, take a look at the Spring blog, consult the reference manual, and check out the Spring MVC Showcase, which includes a large amount of samples of what is possible with the new MVC testing features. Also check out this Spring blog which discusses other new, general testing features such as how you can set up and customize mocked application contexts.

These great new features mean there’s really no excuse not to test controllers, so now we can finally stop starting web servers to find out whether our code works!

One thought on “Spring 3.2 Rundown, MVC Testing

  1. Pingback: Spring 3.2 Rundown, Intro | Not Purely Technical

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>