Configuring Spring MVC Test Framework

After we have finished this lesson, we understand how we can configure the Spring MVC Test framework when we are writing integration tests for a “normal” Spring web application or for a web application that uses Spring Boot.

Writing Integration Tests for a Spring Web Application

If we are writing integration tests for a Spring web application, we can configure the Spring MVC Test framework by following these steps:

First, we have to ensure that the ApplicationContext loaded for our integration test is an instance of the WebApplicationContext class. We can do this by annotating our test class with the @WebAppConfiguration annotation.

After we have annotated our test class with the @WebAppConfiguration annotation, its source code looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import org.junit.experimental.categories.Category;
 5import org.junit.runner.RunWith;
 6import org.springframework.test.context.ContextConfiguration;
 7import org.springframework.test.context.TestExecutionListeners;
 8import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 9import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
10import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
11import org.springframework.test.context.web.WebAppConfiguration;
12
13@RunWith(SpringJUnit4ClassRunner.class)
14@ContextConfiguration(classes = {IntegrationTestContext.class})
15@WebAppConfiguration
16@TestExecutionListeners({
17        DependencyInjectionTestExecutionListener.class,
18        TransactionalTestExecutionListener.class,
19        DbUnitTestExecutionListener.class
20})
21@DatabaseSetup("messages.xml")
22@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
23@Category(IntegrationTest.class)
24public class GetMessageTest {
25
26}

Second, we have to register a new test execution listener called ServletTestExecutionListener. This test execution listener provides mock servlet API support for the WebApplicationContext objects which are loaded by the Spring Test framework.

After we have registered this test execution listener, the source code of our test class looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import org.junit.experimental.categories.Category;
 5import org.junit.runner.RunWith;
 6import org.springframework.test.context.ContextConfiguration;
 7import org.springframework.test.context.TestExecutionListeners;
 8import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 9import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
10import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
11import org.springframework.test.context.web.ServletTestExecutionListener;
12import org.springframework.test.context.web.WebAppConfiguration;
13
14@RunWith(SpringJUnit4ClassRunner.class)
15@ContextConfiguration(classes = {IntegrationTestContext.class})
16@WebAppConfiguration
17@TestExecutionListeners({
18        DependencyInjectionTestExecutionListener.class,
19        TransactionalTestExecutionListener.class,
20        DbUnitTestExecutionListener.class,
21        ServletTestExecutionListener.class
22})
23@DatabaseSetup("messages.xml")
24@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
25@Category(IntegrationTest.class)
26public class GetMessageTest {
27
28}

Third, we have to add the following fields into our integration test class:

  1. The webAppContext field contains the WebApplicationContext object that is loaded by the Spring Test framework.
  2. The mockMvc field contains the MockMvc object that we use when we write integration tests for our controllers.

After we have added these fields into our test class, its source code looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import org.junit.experimental.categories.Category;
 5import org.junit.runner.RunWith;
 6import org.springframework.beans.factory.annotation.Autowired;
 7import org.springframework.test.context.ContextConfiguration;
 8import org.springframework.test.context.TestExecutionListeners;
 9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
11import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
12import org.springframework.test.context.web.ServletTestExecutionListener;
13import org.springframework.test.context.web.WebAppConfiguration;
14import org.springframework.test.web.servlet.MockMvc;
15import org.springframework.web.context.WebApplicationContext;
16
17@RunWith(SpringJUnit4ClassRunner.class)
18@ContextConfiguration(classes = {IntegrationTestContext.class})
19@WebAppConfiguration
20@TestExecutionListeners({
21        DependencyInjectionTestExecutionListener.class,
22        TransactionalTestExecutionListener.class,
23        DbUnitTestExecutionListener.class,
24        ServletTestExecutionListener.class
25})
26@DatabaseSetup("messages.xml")
27@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
28@Category(IntegrationTest.class)
29public class GetMessageTest {
30
31    @Autowired
32    private WebApplicationContext webAppContext;
33
34    private MockMvc mockMvc;
35}

Fourth, we have to create the MockMvc object that we use when we write integration tests for our controllers. We can create this object by following these steps:

  1. Add a setup method into our test class. We will create the required MockMvc object in this method.
  2. Create a new MockMvc object by using the web application context based setup and set the created object to the mockMvc field.

After added a new setup method into our test class, its source code looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import org.junit.Before;
 5import org.junit.experimental.categories.Category;
 6import org.junit.runner.RunWith;
 7import org.springframework.beans.factory.annotation.Autowired;
 8import org.springframework.test.context.ContextConfiguration;
 9import org.springframework.test.context.TestExecutionListeners;
10import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
12import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
13import org.springframework.test.context.web.ServletTestExecutionListener;
14import org.springframework.test.context.web.WebAppConfiguration;
15import org.springframework.test.web.servlet.MockMvc;
16import org.springframework.test.web.servlet.setup.MockMvcBuilders;
17import org.springframework.web.context.WebApplicationContext;
18
19@RunWith(SpringJUnit4ClassRunner.class)
20@ContextConfiguration(classes = {IntegrationTestContext.class})
21@WebAppConfiguration
22@TestExecutionListeners({
23        DependencyInjectionTestExecutionListener.class,
24        TransactionalTestExecutionListener.class,
25        DbUnitTestExecutionListener.class,
26        ServletTestExecutionListener.class
27})
28@DatabaseSetup("messages.xml")
29@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
30@Category(IntegrationTest.class)
31public class GetMessageTest {
32
33    @Autowired
34    private WebApplicationContext webAppContext;
35
36    private MockMvc mockMvc;
37
38    @Before
39    public void configureSystemUnderTest() {
40        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
41                .build();
42    }
43}

We have now configured the Spring MVC Test framework by using the web application context based configuration, and we can start writing integration tests for our controllers.

Let’s find out how we can configure the Spring MVC Test framework when we are using Spring Boot.

Writing Integration Tests for a Spring Boot Web Application

If we are writing integration tests for a web application that uses Spring Boot, we can configure the Spring MVC Test framework by following these steps:

First, we have to enable the auto-configuration of the Spring MVC Test framework. We can enable this Spring Boot feature by annotating our test class with the @AutoConfigureMockMvc annotation.

After we have annotated our test class with this annotation, the source code of our test class looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import org.junit.experimental.categories.Category;
 5import org.junit.runner.RunWith;
 6import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 7import org.springframework.boot.test.context.SpringBootTest;
 8import org.springframework.test.context.TestExecutionListeners;
 9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
11import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
12
13@RunWith(SpringJUnit4ClassRunner.class)
14@SpringBootTest(classes = {IntegrationTestContext.class})
15@AutoConfigureMockMvc
16@TestExecutionListeners({
17        DependencyInjectionTestExecutionListener.class,
18        TransactionalTestExecutionListener.class,
19        DbUnitTestExecutionListener.class
20})
21@DatabaseSetup("messages.xml")
22@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
23@Category(IntegrationTest.class)
24public class GetMessageTest {
25
26}

Second, we have to register a new test execution listener called ServletTestExecutionListener. This test execution listener provides mock servlet API support for the WebApplicationContext objects which are loaded by the Spring Test framework.

After we have registered this test execution listener, the source code of our test class looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import org.junit.experimental.categories.Category;
 5import org.junit.runner.RunWith;
 6import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 7import org.springframework.boot.test.context.SpringBootTest;
 8import org.springframework.test.context.TestExecutionListeners;
 9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
11import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
12import org.springframework.test.context.web.ServletTestExecutionListener;
13
14@RunWith(SpringJUnit4ClassRunner.class)
15@SpringBootTest(classes = {IntegrationTestContext.class})
16@AutoConfigureMockMvc
17@TestExecutionListeners({
18        DependencyInjectionTestExecutionListener.class,
19        TransactionalTestExecutionListener.class,
20        DbUnitTestExecutionListener.class,
21        ServletTestExecutionListener.class
22})
23@DatabaseSetup("messages.xml")
24@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
25@Category(IntegrationTest.class)
26public class GetMessageTest {
27
28}

Third, we have to add a new MockMvc field into our test class and ensure that the real MockMvc object is injected into this field by the Spring container.

After we have added this field into our test class, its source code looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import org.junit.experimental.categories.Category;
 5import org.junit.runner.RunWith;
 6import org.springframework.beans.factory.annotation.Autowired;
 7import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 8import org.springframework.boot.test.context.SpringBootTest;
 9import org.springframework.test.context.TestExecutionListeners;
10import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
12import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
13import org.springframework.test.context.web.ServletTestExecutionListener;
14import org.springframework.test.web.servlet.MockMvc;
15
16@RunWith(SpringJUnit4ClassRunner.class)
17@SpringBootTest(classes = {IntegrationTestContext.class})
18@AutoConfigureMockMvc
19@TestExecutionListeners({
20        DependencyInjectionTestExecutionListener.class,
21        TransactionalTestExecutionListener.class,
22        DbUnitTestExecutionListener.class,
23        ServletTestExecutionListener.class
24})
25@DatabaseSetup("messages.xml")
26@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
27@Category(IntegrationTest.class)
28public class GetMessageTest {
29
30    @Autowired
31    private MockMvc mockMvc;
32}

We have now configured the Spring MVC Test framework by using the auto-configuration feature provided by Spring Boot, and we can start writing integration tests for our controllers.

Let’s summarize what we learned from this lesson.

Summary

This lesson has taught us two things:

  • If we are writing integration tests for a Spring web application, we have to create the required MockMvc object by using the web application context based configuration.
  • If we are writing integration tests for a Spring Boot web application, we can create the required MockMvc object by using the auto-configuration feature of Spring Boot.

Get the source code from Github