Setup Choices

MockMvc can be setup in one of two ways. One is to point directly to the controllers you want to test and programmatically configure Web MVC infrastructure. The second is to point to Infra configuration with Web MVC and controller infrastructure in it.

To set up MockMvc for testing a specific controller, use the following:

class MyWebTests {

  MockMvc mockMvc;

  @BeforeEach
  void setup() {
    this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();
  }

  // ...

}

Or you can also use this setup when testing through the WebTestClient which delegates to the same builder as shown above.

To set up MockMvc through Infra configuration, use the following:

@JUnitWebConfig(locations = "my-servlet-context.xml")
class MyWebTests {

  MockMvc mockMvc;

  @BeforeEach
  void setup(WebApplicationContext wac) {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
  }

  // ...

}

Or you can also use this setup when testing through the WebTestClient which delegates to the same builder as shown above.

Which setup option should you use?

The webAppContextSetup loads your actual Web MVC configuration, resulting in a more complete integration test. Since the TestContext framework caches the loaded Infra configuration, it helps keep tests running fast, even as you introduce more tests in your test suite. Furthermore, you can inject mock services into controllers through Infra configuration to remain focused on testing the web layer. The following example declares a mock service with Mockito:

<bean id="accountService" class="org.mockito.Mockito" factory-method="mock">
  <constructor-arg value="org.example.AccountService"/>
</bean>

You can then inject the mock service into the test to set up and verify your expectations, as the following example shows:

@JUnitWebConfig(locations = "test-servlet-context.xml")
class AccountTests {

  @Autowired
  AccountService accountService;

  MockMvc mockMvc;

  @BeforeEach
  void setup(WebApplicationContext wac) {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
  }

  // ...

}

The standaloneSetup, on the other hand, is a little closer to a unit test. It tests one controller at a time. You can manually inject the controller with mock dependencies, and it does not involve loading Infra configuration. Such tests are more focused on style and make it easier to see which controller is being tested, whether any specific Infra MVC configuration is required to work, and so on. The standaloneSetup is also a very convenient way to write ad-hoc tests to verify specific behavior or to debug an issue.

As with most “integration versus unit testing” debates, there is no right or wrong answer. However, using the standaloneSetup does imply the need for additional webAppContextSetup tests in order to verify your Web MVC configuration. Alternatively, you can write all your tests with webAppContextSetup, in order to always test against your actual Web MVC configuration.