Since Spring 3.2 (January 2013), it has become possible to test Spring MVC controllers without an external framework. This article demonstrates how to test Spring MVC controllers using only Spring’s built-in testing capabilities.
To do so, a simple Spring Boot project will be used as support. You can find it on GitHub. First, we will present the controller to test, and then we will explain how to test it.
Controller
The controller to test is shown below. It allows performing a search in a fruit list.
@Controller
public class ApplicationController {
@RequestMapping(value = "/fruits", method = RequestMethod.GET)
public String getFruits(@RequestParam(value = "search", required = false) String search, final Model model) {
model.addAttribute("fruitBowl", search(search));
return "fruits";
}
private List<String> search(String search) {
if (StringUtils.isEmpty(search)) {
return fruitBowl();
}
return fruitBowl().stream()
.filter(fruit -> fruit.startsWith(search))
.collect(toList());
}
private List<String> fruitBowl() {
return asList("banana", "orange");
}
}
Test
Annotate the test class as follows:
@RunWith(SpringJUnit4ClassRunner.class)
to benefit from Spring features in JUnit tests.@SpringApplicationConfiguration(classes = DemoTestSpringMvcApplication.class)
to specify the configuration class used during the test.@WebAppConfiguration
to indicate that the Spring application context to load is aWebApplicationContext
.
The entry point to perform the tests is the class MockMvc
. Below, we will explain its usage.
Set up
Set up the MockMvc
class as follows:
@Before
public void setUp() {
ApplicationController controller = new ApplicationController(); // 1
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); // 2
}
First, instantiate the controller (1
). Then, initialize the mock using the static method MockMvcBuilders.standaloneSetup()
(2
). At this point, the mock is ready to test the controller.
Perform
The method MockMvc.perform()
simulates HTTP requests to the controller. For instance, a GET request is made as follows:
mockMvc.perform(
get("/fruits") // 1
.param("search", "ban") // 2
);
The class MockMvcRequestBuilders
provides static methods like get
or post
to simulate HTTP requests on a particular endpoint of the controller (1
). You can add HTTP parameters to the request fluently (2
).
MockMvcRequestBuilders
also provides other static methods:
- HTTP verbs like
delete
,put
orpatch
. fileUpload
for uploading binary files.- Others (documentation).
Assert
MockMvc allows adding assertions to the controller’s response.
mockMvc.perform(get("/fruits")
.param("search", "ban"))
.andExpect(status().isOk()) // 1
.andExpect(view().name("fruits")) // 2
.andExpect(model().attribute("fruitBowl", contains("banana"))); // 3
Assertions are done with the andExpect()
method. And, the MockMvcResultMatchers
class provides static methods to perform assertions on the HTTP status (1
), the view asked by the controller (2
) and the model completed by the controller (3
).
Conclusion
The Spring test framework is a powerful, complete and straightforward way to test Spring MVC controllers. Its fluent API makes it possible to write elegant yet precise tests.