Introducing Spring MVC test framework

1

Spring MVC comes with a very useful test framework, which allows doing in-depth testing without even starting a web container. If you struggle maintaining any application based on Spring MVC, this post will show you the basics of the Spring MVC test framework.

What am I testing?

We can distinguish 3 levels of testing for Spring MVC controllers:

  • unit tests: we test only the logic of the controller. Dependencies are mocked/stubbed, there’s no Spring, nor web container. Spring MVC POJO programming model allows writing such tests easily. These tests are only useful when there’s some complex logic inside controllers.
  • out-of-container integration test: we test the controller logic as well as the surrounding plumbing. This plumbing is typically validation or data binding/serialization enforced by the framework. Dependencies are usually mocked/stubbed, but we need a diminished version of the infrastructure (a mock Spring MVC, but no web container).
  • end-to-end testing: we test the whole stack of our application, from the controller to the database, through the service and data access layers. One can write such tests by starting an embedded Jetty in a JUnit test, and using HtmlUnit or REST-assured for the testing itself.

This post focuses on the second level of testing, by using the Spring MVC test framework, available as of Spring 3.2. Here are some scenarios where this test framework comes in handy:

testing inbound/outbound serialization (e.g. JSON to Java for incoming requests and Java to JSON for responses)

testing validation rules (forms and JSR 303, enforced by Spring MVC)

testing content negotiation (e.g. sending the Accept header with a given value and checking we get the appropriate content-type)

testing response codes (e.g. 201 for a successful creation)

testing the availability of headers in the response (e.g. the Location after a creation)

The Spring MVC test framework makes all of this a breeze, let’s see how to use it to test a simple web controller.

The controller to test

The controller we’re about to test is the usual “Hello World” example for Spring MVC:

Here is a quick reminder about the used annotations:

@Controller: to mark the class as a controller. Without this annotation, Spring MVC wouldn’t pick up the corresponding bean.

@RequestMapping: to map the method on a given URL (and HTTP method if necessary).

@ResponseBody: to send the returned object directly into the response. We don’t want any view rendering here.

Let’s move on to the writing of the test.

The testing framework

Here are the steps to write the test.

Setting up the test class

Setting up a Spring MVC test class is pretty much the same as for any test based on the Spring TestContext Framework, except for one new annotation – @WebAppConfiguration – to create a web version of the Spring application context:

Note we’re configuring the Spring application context directly in the test, by declaring a static @Configuration inner class. The test framework will pick it up automatically.

Bootstrapping the Spring MVC test environment

The MockMvc will mock all the Spring MVC infrastructure. We just need the Spring application context to create it. We do this in the @Before method of our test:

Testing the controller

Our test has 2 steps:

  • creating the mock HTTP request (URL, headers, parameters, etc)
  • checking the HTTP response (content type, content, etc)

The test framework a comprehensive API for request creation and response expectation. Let’s use first an explicit version of this API:

The code is quite simple to understand, but it remains verbose. We can simplify it by adding the following static imports:

If you have an hard time remembering these classes, note they’re all starting with MockMvc*.

The full version of the test benefits from the static imports:

The test method is now shorter and easier to read, thanks to the fluent API.

All of this is quite abstract, and I’m sure any developer needs to see the actual request and response. This can be easily done by adding a static import and using the print ResultHandler:

By using andDo(print()), we end up with the following output on the console:

This should make debugging much simpler. Note ResultHandler is a very useful extension point for any action you need to perform on the response.

Conclusion

This introduction covered the basics of the Spring MVC test framework. We tested a simple GET method, but the framework can do much more: sending parameters and a given content in the request, checking more complex content like JSON in the response, etc. And all of this with an efficient and fluent API. The Spring MVC test framework is the perfect tool to test thoroughly and quickly your web controllers.

Stay tuned, a subsequent post will show you how to test a typical JSON-based REST controller.

Source code

Partagez cet article.

A propos de l'auteur

Un commentaire

Ajouter un commentaire