REST Web Services testing with Spring MVC
A previous post introduced the basic features of the Spring MVC test framework. This post covers the testing of a REST web controller: by checking the response status, the content type, and the returned JSON document , we’ll verify if the controller behaves as expected.
The controller to test
The controller to test is rather simple, it just returns a Java object that ends up being serialized in the response. The point here is to test Spring MVC features like argument mapping and serialization.
@Controller
public class ContactController {
@RequestMapping("/contact/{id}")
@ResponseBody
public Contact contact(@PathVariable("id") Integer id) {
// mimics a call to a business service
return new Contact(id,"Test Firstname","Test Lastname");
}
}
The test of the controller
Setting up the test
We need to set up the web version (@WebAppConfiguration) of the Spring TestContext Framework (@RunWith(SpringJUnit4ClassRunner.class) and @ContextConfiguration). We embed the configuration in the test, thanks to a @Configuration inner class. Here is the setup part of the test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class ContactControllerTest {
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
(...)
@Configuration
@EnableWebMvc
public static class TestConfiguration {
@Bean
public ContactController contactController() {
return new ContactController();
}
}
}
Note we use @EnableWebMvc on the configuration class: this will activate (among others) the REST support. We need this to register the Jackson (JSON) converter in charge of serialization.
The infrastructure is ready, let’s send a (mock) request to our controller.
Sending a request, debugging the response
The whole point of the test is to ensure the controller responds correctly to one of our requests. Our controller is quite simple, so we could send a request and directly check the result with the appropriate expectation API. For more complex cases, like fancy custom JSON serialization, we would typically send the request and use some debugging features to display the response. This would make the writing of the expectations simpler (especially if the returned document is somewhat complex). Let’s do that!
Our first version of the test method sends the request and use andDo(print()) to display the request and response information on the console:
@Test
public void contact() throws Exception {
Integer id = 1;
mockMvc.perform(get("/contact/{id}",id).accept(MediaType.APPLICATION_JSON))
.andDo(print());
}
The execution of the test should output the following on the console:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /contact/1
Parameters = {}
Headers = {Accept=[application/json]}
Handler:
Type = com.zenika.ContactController
Method = public com.zenika.Contact com.zenika.ContactController.contact(java.lang.Integer)
Async:
Was async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"id":1,"firstname":"Test Firstname","lastname":"Test Lastname"}
Forwarded URL = null
Redirected URL = null
Cookies = []
In real-world tests, you would typically check the response status, the headers, and the body:
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"id":1,"firstname":"Test Firstname","lastname":"Test Lastname"}
Let’s see how to do that.
Checking the response
We check the response by calling the andExpect method on the ResultActions object returned by the perform method. The andExpect needs a ResultMatcher object and we would typically use ResultMatchers provided by the MockMvcResultMatchers class.
To check the response code, we use the status() method. We expect 200 (OK):
.andExpect(status().isOk())
To check the content type:
.andExpect(content().contentType("application/json;charset=UTF-8"))
Testing the JSON document can be a pain, especially if you don’t have support for JSON parsing. The good news is Spring MVC test framework supports JsonPath out-of-the-box. Retrieving the value of the id attribute is like the following:
.andExpect(jsonPath("id").value(id));
Let’s put it all together, here is the full test method:
@Test
public void contact() throws Exception {
Integer id = 1;
mockMvc.perform(get("/contact/{id}",id).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"))
.andExpect(jsonPath("id").value(id));
}
Pretty simple, isn’t it? Launch the test in your favorite IDE to see the green bar!
And here’s the full version of the test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class ContactControllerTest {
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
@Test
public void contact() throws Exception {
Integer id = 1;
mockMvc.perform(get("/contact/{id}",id).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"))
.andExpect(jsonPath("id").value(id));
}
@Configuration
@EnableWebMvc
public static class TestConfiguration {
@Bean
public ContactController contactController() {
return new ContactController();
}
}
}
Conclusion
This post covered how to test a Spring MVC REST controller with the Spring MVC out-of-container test framework. We managed to check the controller in terms of input parameters, response status, response headers, and response content. By testing a read-only web service, we only scratched the surface of the framework: one can test the other HTTP operations (POST, PUT, DELETE), requests with some content in the body, more headers, etc. Now, get back to work and test your REST web service layer!
Source code

Hi
Great post and everything clearly explained.
I was wondering how to compare string from response body (not json) with that andExpect()
I know that mockMvc has andReturn() so whole expression can return response – but I wonder that is possible to check simple string against that in body within mockMvc expression?