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 a WebApplicationContext.

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 or patch.
  • 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.