Writing Integration Tests for "Normal" Controllers - Rendering Data

After we have finished this lesson, we

  • Understand what kind of test data we should use when we write integration tests for controller methods that find information from the database.
  • Know how we can write integration tests for controller methods that render data found from the database.

Use Case 1: Rendering the Information of a Single Task

Introduction to System Under Test

We have to write integration tests for a controller method that processes GET requests send to the path: ‘/task/{taskId}’. This method is called showTask() and it is implemented by following these steps:

  1. Find the task from the database.
  2. Put the found task to a model attribute called: task.
  3. Return the name of the view (’task/view’) that renders the information of the found task.

The source code of the tested controller method looks as follows:

 1import com.testwithspring.intermediate.task.TaskCrudService;
 2import com.testwithspring.intermediate.task.TaskDTO;
 3import org.springframework.beans.factory.annotation.Autowired;
 4import org.springframework.context.MessageSource;
 5import org.springframework.stereotype.Controller;
 6import org.springframework.ui.Model;
 7import org.springframework.web.bind.annotation.PathVariable;
 8import org.springframework.web.bind.annotation.RequestMapping;
 9import org.springframework.web.bind.annotation.RequestMethod;
10
11@Controller
12public class TaskCrudController {
13
14    private final TaskCrudService crudService;
15    private final MessageSource messageSource;
16
17    @Autowired
18    TaskCrudController(TaskCrudService crudService,
19                       MessageSource messageSource) {
20        this.crudService = crudService;
21        this.messageSource = messageSource;
22    }
23
24    @RequestMapping(value = "/task/{taskId}", method = RequestMethod.GET)
25    public String showTask(@PathVariable("taskId") Long taskId, Model model) {
26        TaskDTO task = crudService.findById(taskId);
27        model.addAttribute("task", task);
28        return "task/view";
29    }
30}

The TaskDTO class is a DTO that contains the information of a single task. Its source code looks as follows:

 1import java.time.ZonedDateTime;
 2import java.util.ArrayList;
 3import java.util.List;
 4
 5public class TaskDTO {
 6
 7    private Long assigneeId;
 8    private Long closerId;
 9    private ZonedDateTime creationTime;
10    private Long creatorId;
11    private String description;
12    private Long id;
13    private ZonedDateTime modificationTime;
14    private TaskResolution resolution;
15    private TaskStatus status;
16    private List<TagDTO> tags = new ArrayList<>();
17    private String title;
18
19	//Getters and setters are omitted
20}

The TagDTO class is a DTO that contains the information of a single tag. Its source code looks as follows:

1public class TagDTO {
2
3    private Long id;
4    private String name;
5
6	//Getters and setters are omitted
7}

Next, we will write integration tests which ensure that the showTask() method is working as expected when the requested task is found. Let’s start by initializing our database into a known state.

Initializing Our Database Into a Known State

When we want to initialize our database into a known state, we will use the same DbUnit data set that we created in the previous lesson . It’s a good idea to reuse DbUnit data sets because it helps us to reduce maintenance efforts that are required when we make changes to our database.

However, because the tested controller method shows the information of the tags found from the database, we have to add two rows into tags table and link these rows with the tasks found from our database.

After we have added these rows into the our DbUnit data set (tasks.xml), its source code looks as follows:

 1<dataset>
 2    <tasks id="1"
 3           assignee_id="1"
 4           closer_id="1"
 5           creation_time="2016-12-3 11:41:28"
 6           creator_id="1"
 7           description="This example contains integration tests"
 8           modification_time="2016-12-3 11:41:28"
 9           resolution="DONE"
10           status="CLOSED"
11           title="Write example application"
12           version="0"/>
13    <tasks id="2"
14           assignee_id="[null]"
15           closer_id="[null]"
16           creation_time="2016-12-4 11:41:28"
17           creator_id="1"
18           description="This lesson talks about integration testing"
19           modification_time="2016-12-4 11:41:28"
20           resolution="[null]"
21           status="OPEN"
22           title="Write lesson"
23           version="0"/>
24
25    <tags id="1"
26          creation_time="2016-12-3 11:41:28"
27          modification_time="2016-12-3 11:41:28"
28          name="example"
29          version="0"/>
30    <tags id="2"
31          creation_time="2016-12-3 11:41:28"
32          modification_time="2016-12-3 11:41:28"
33          name="lesson"
34          version="0"/>
35
36    <tasks_tags task_id="1" tag_id="1"/>
37    <tasks_tags task_id="2" tag_id="2"/>
38</dataset>

After we have made the required changes to our DbUnit data set, we have to make the following changes to the constant class that contains the information of the tasks found from our database:

  1. Create a method that transforms a timestamp string into a ZonedDateTime object. This method ensures that the created object uses the system’s default time zone. This means that we can run our integration tests in different time zones without making any changes to our test data.
  2. Declare the constants that contain the column values of the tasks found from the tasks table. Also, we must remember to use our new utility method when we declare constants that contain date and time information.
  3. Declare the constants that contain the column values of the tags found from the database.

After we have added the required constants into the Tasks class, its source code looks as follows:

 1import java.time.ZoneId;
 2import java.time.ZonedDateTime;
 3import java.time.format.DateTimeFormatter;
 4
 5public final class Tasks {
 6
 7    private Tasks() {}
 8
 9    public static final String SEARCH_TERM_ONE_MATCH = "Esso";
10    public static final String SEARCH_TERM_NOT_FOUND = "NO_PE";
11
12    public static class WriteExampleApp {
13
14        public static final Long ASSIGNEE_ID = 1L;
15        public static final Long CLOSER_ID = 1L;
16        public static final ZonedDateTime CREATION_TIME = parseDateTime("2016-12-03T11:41:28");
17        public static final Long CREATOR_ID = 1L;
18        public static final String DESCRIPTION = "This example contains integration tests";
19        public static final Long ID = 1L;
20        public static final ZonedDateTime MODIFICATION_TIME = parseDateTime("2016-12-03T11:41:28");
21        public static final TaskResolution RESOLUTION = TaskResolution.DONE;
22        public static final TaskStatus STATUS = TaskStatus.CLOSED;
23        public static final String TITLE = "Write example application";
24
25        public static class Tags {
26
27            public static class Example {
28
29                public static final Long ID = 1L;
30                public static final String NAME = "example";
31            }
32        }
33    }
34
35    public static class WriteLesson {
36
37        public static final ZonedDateTime CREATION_TIME =  parseDateTime("2016-12-04T11:41:28");
38        public static final Long CREATOR_ID = 1L;
39        public static final String DESCRIPTION = "This lesson talks about integration testing";
40        public static final Long ID = 2L;
41        public static final ZonedDateTime MODIFICATION_TIME =  parseDateTime("2016-12-04T11:41:28");
42        public static final TaskStatus STATUS = TaskStatus.OPEN;
43        public static final String TITLE = "Write lesson";
44
45        public static class Tags {
46
47            public static class Lesson {
48
49                public static final Long ID = 1L;
50                public static final String NAME = "lesson";
51            }
52        }
53    }
54
55    private static ZonedDateTime parseDateTime(String dateTime) {
56        dateTime += getSystemZoneOffset();
57        dateTime += getSystemZoneId();
58
59        return ZonedDateTime.from(DateTimeFormatter.ISO_ZONED_DATE_TIME.parse(dateTime));
60    }
61
62    private static String getSystemZoneOffset() {
63        return ZonedDateTime.now().getOffset().toString();
64    }
65
66    private static String getSystemZoneId() {
67        return "[" + ZoneId.systemDefault().toString() + "]";
68    }
69}

After we have created our DbUnit data set, we can write integration tests for the tested controller method.

Writing Our Integration Tests

Before we can write the actual integration tests, we have to add test specific configuration into our test class. We can configure our test cases by following these steps:

  1. Configure the DbUnit data set that initializes our database into known state. Because we are writing integration tests for a finder method, all test methods can use the same data set.
  2. Create a private method that sends a GET request to the path: ‘/task/1’. This method returns a ResultActions object, and its goal is to help us to reduce duplicate code which is often found from test classes that use the Spring MVC Test framework.

After we have configured our test cases, 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.Before;
 5import org.junit.experimental.categories.Category;
 6import org.junit.runner.RunWith;
 7import org.springframework.beans.factory.annotation.Autowired;
 8import org.springframework.test.context.ActiveProfiles;
 9import org.springframework.test.context.ContextConfiguration;
10import org.springframework.test.context.TestExecutionListeners;
11import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
12import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
13import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
14import org.springframework.test.context.web.ServletTestExecutionListener;
15import org.springframework.test.context.web.WebAppConfiguration;
16import org.springframework.test.web.servlet.MockMvc;
17import org.springframework.test.web.servlet.ResultActions;
18import org.springframework.test.web.servlet.setup.MockMvcBuilders;
19import org.springframework.web.context.WebApplicationContext;
20
21import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
22
23@RunWith(SpringJUnit4ClassRunner.class)
24@ContextConfiguration(classes = {IntegrationTestContext.class})
25@WebAppConfiguration
26@TestExecutionListeners({
27        DependencyInjectionTestExecutionListener.class,
28        TransactionalTestExecutionListener.class,
29        DbUnitTestExecutionListener.class,
30        ServletTestExecutionListener.class
31})
32@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
33@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
34@Category(IntegrationTest.class)
35@ActiveProfiles(Profiles.INTEGRATION_TEST)
36public class ShowTaskWhenTaskIsFoundTest {
37
38    @Autowired
39    private WebApplicationContext webAppContext;
40
41    private MockMvc mockMvc;
42
43    @Before
44    public void configureSystemUnderTest() {
45        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
46                .build();
47    }
48
49    private ResultActions openShowTaskPage() throws Exception {
50        return mockMvc.perform(get("/task/{taskId}",
51                Tasks.WriteExampleApp.ID
52        ));
53    }
54}
If you don’t know how you can configure your integration tests, you should take a look at the Configuring Our Integration Tests topic.

After we have configured our test cases, we have to write six integration tests for the showTask() method. These tests ensure that the showTask() method is working as expected when the requested task is found.

First, we have to verify that the tested controller method returns the HTTP status code 200. After we have written this integration test, 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
23import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
24
25@RunWith(SpringJUnit4ClassRunner.class)
26@ContextConfiguration(classes = {IntegrationTestContext.class})
27@WebAppConfiguration
28@TestExecutionListeners({
29        DependencyInjectionTestExecutionListener.class,
30        TransactionalTestExecutionListener.class,
31        DbUnitTestExecutionListener.class,
32        ServletTestExecutionListener.class
33})
34@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
35@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
36@Category(IntegrationTest.class)
37@ActiveProfiles(Profiles.INTEGRATION_TEST)
38public class ShowTaskWhenTaskIsFoundTest {
39
40    @Autowired
41    private WebApplicationContext webAppContext;
42
43    private MockMvc mockMvc;
44
45    @Before
46    public void configureSystemUnderTest() {
47        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
48                .build();
49    }
50
51    @Test
52    public void shouldReturnHttpStatusCodeOk() throws Exception {
53        openShowTaskPage()
54                .andExpect(status().isOk());
55    }
56
57    private ResultActions openShowTaskPage() throws Exception {
58        return  mockMvc.perform(get("/task/{taskId}",
59                Tasks.WriteExampleApp.ID
60        ));
61    }
62}

Second, we have to ensure that the tested controller method renders the view task view (’task/view’). After we have written this integration test, the relevant part of our integration 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
23import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
24
25@RunWith(SpringJUnit4ClassRunner.class)
26@ContextConfiguration(classes = {IntegrationTestContext.class})
27@WebAppConfiguration
28@TestExecutionListeners({
29        DependencyInjectionTestExecutionListener.class,
30        TransactionalTestExecutionListener.class,
31        DbUnitTestExecutionListener.class,
32        ServletTestExecutionListener.class
33})
34@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
35@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
36@Category(IntegrationTest.class)
37@ActiveProfiles(Profiles.INTEGRATION_TEST)
38public class ShowTaskWhenTaskIsFoundTest {
39
40    @Autowired
41    private WebApplicationContext webAppContext;
42
43    private MockMvc mockMvc;
44
45    @Before
46    public void configureSystemUnderTest() {
47        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
48                .build();
49    }
50
51    @Test
52    public void shouldRenderShowTaskView() throws Exception {
53        openShowTaskPage()
54                .andExpect(view().name("task/view"));
55    }
56
57    private ResultActions openShowTaskPage() throws Exception {
58        return  mockMvc.perform(get("/task/{taskId}",
59                Tasks.WriteExampleApp.ID
60        ));
61    }
62}

Third, we have to verify that the tested controller method forwards the user to the show task page. After we have written this integration test, the relevant part 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 com.testwithspring.intermediate.IntegrationTest;
 5import com.testwithspring.intermediate.IntegrationTestContext;
 6import com.testwithspring.intermediate.ReplacementDataSetLoader;
 7import com.testwithspring.intermediate.Tasks;
 8import com.testwithspring.intermediate.config.Profiles;
 9import org.junit.Before;
10import org.junit.Test;
11import org.junit.experimental.categories.Category;
12import org.junit.runner.RunWith;
13import org.springframework.beans.factory.annotation.Autowired;
14import org.springframework.test.context.ActiveProfiles;
15import org.springframework.test.context.ContextConfiguration;
16import org.springframework.test.context.TestExecutionListeners;
17import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
18import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
19import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
20import org.springframework.test.context.web.ServletTestExecutionListener;
21import org.springframework.test.context.web.WebAppConfiguration;
22import org.springframework.test.web.servlet.MockMvc;
23import org.springframework.test.web.servlet.ResultActions;
24import org.springframework.test.web.servlet.setup.MockMvcBuilders;
25import org.springframework.web.context.WebApplicationContext;
26
27import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
28import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
29
30@RunWith(SpringJUnit4ClassRunner.class)
31@ContextConfiguration(classes = {IntegrationTestContext.class})
32@WebAppConfiguration
33@TestExecutionListeners({
34        DependencyInjectionTestExecutionListener.class,
35        TransactionalTestExecutionListener.class,
36        DbUnitTestExecutionListener.class,
37        ServletTestExecutionListener.class
38})
39@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
40@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
41@Category(IntegrationTest.class)
42@ActiveProfiles(Profiles.INTEGRATION_TEST)
43public class ShowTaskWhenTaskIsFoundTest {
44
45    @Autowired
46    private WebApplicationContext webAppContext;
47
48    private MockMvc mockMvc;
49
50    @Before
51    public void configureSystemUnderTest() {
52        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
53                .build();
54    }
55
56    @Test
57    public void shouldForwardUserToShowTaskPageUrl() throws Exception {
58        openShowTaskPage()
59                .andExpect(forwardedUrl("/WEB-INF/jsp/task/view.jsp"));
60    }
61
62    private ResultActions openShowTaskPage() throws Exception {
63        return  mockMvc.perform(get("/task/{taskId}",
64                Tasks.WriteExampleApp.ID
65        ));
66    }
67}
If we are not using JSP views, we don’t have to write this integration test because our controller can render the requested view without forwarding user to view page. Instead, it will read the content of the view from the template file and return the content of the rendered view in the response body.

Fourth, we have to verify that the tested controller method shows the information of the found task. After we have written this integration test, the relevant part 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 com.testwithspring.intermediate.IntegrationTest;
  5import com.testwithspring.intermediate.IntegrationTestContext;
  6import com.testwithspring.intermediate.ReplacementDataSetLoader;
  7import com.testwithspring.intermediate.Tasks;
  8import com.testwithspring.intermediate.config.Profiles;
  9import org.junit.Before;
 10import org.junit.Test;
 11import org.junit.experimental.categories.Category;
 12import org.junit.runner.RunWith;
 13import org.springframework.beans.factory.annotation.Autowired;
 14import org.springframework.test.context.ActiveProfiles;
 15import org.springframework.test.context.ContextConfiguration;
 16import org.springframework.test.context.TestExecutionListeners;
 17import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 18import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
 19import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
 20import org.springframework.test.context.web.ServletTestExecutionListener;
 21import org.springframework.test.context.web.WebAppConfiguration;
 22import org.springframework.test.web.servlet.MockMvc;
 23import org.springframework.test.web.servlet.ResultActions;
 24import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 25import org.springframework.web.context.WebApplicationContext;
 26
 27import static org.hamcrest.Matchers.*;
 28import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 29import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
 30import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 31
 32@RunWith(SpringJUnit4ClassRunner.class)
 33@ContextConfiguration(classes = {IntegrationTestContext.class})
 34@WebAppConfiguration
 35@TestExecutionListeners({
 36        DependencyInjectionTestExecutionListener.class,
 37        TransactionalTestExecutionListener.class,
 38        DbUnitTestExecutionListener.class,
 39        ServletTestExecutionListener.class
 40})
 41@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
 42@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
 43@Category(IntegrationTest.class)
 44@ActiveProfiles(Profiles.INTEGRATION_TEST)
 45public class ShowTaskWhenTaskIsFoundTest {
 46
 47    @Autowired
 48    private WebApplicationContext webAppContext;
 49
 50    private MockMvc mockMvc;
 51
 52    @Before
 53    public void configureSystemUnderTest() {
 54        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
 55                .build();
 56    }
 57
 58    @Test
 59    public void shouldReturnHttpStatusCodeOk() throws Exception {
 60        openShowTaskPage()
 61                .andExpect(status().isOk());
 62    }
 63
 64    @Test
 65    public void shouldShowFoundTask() throws Exception {
 66        openShowTaskPage()
 67                .andExpect(model().attribute("task", allOf(
 68                        hasProperty("assigneeId",
 69                                is(Tasks.WriteExampleApp.ASSIGNEE_ID)
 70                        ),
 71                        hasProperty("closerId",
 72                                is(Tasks.WriteExampleApp.CLOSER_ID)
 73                        ),
 74                        hasProperty("creationTime",
 75                                is(Tasks.WriteExampleApp.CREATION_TIME)
 76                        ),
 77                        hasProperty("creatorId",
 78                                is(Tasks.WriteExampleApp.CREATOR_ID)
 79                        ),
 80                        hasProperty("id",
 81                                is(Tasks.WriteExampleApp.ID)
 82                        ),
 83                        hasProperty("modificationTime",
 84                                is(Tasks.WriteExampleApp.MODIFICATION_TIME)
 85                        ),
 86                        hasProperty("title",
 87                                is(Tasks.WriteExampleApp.TITLE)
 88                        ),
 89                        hasProperty("description",
 90                                is(Tasks.WriteExampleApp.DESCRIPTION)
 91                        ),
 92                        hasProperty("status",
 93                                is(Tasks.WriteExampleApp.STATUS)
 94                        ),
 95                        hasProperty("resolution",
 96                                is(Tasks.WriteExampleApp.RESOLUTION)
 97                        )
 98                )));
 99    }
100
101    private ResultActions openShowTaskPage() throws Exception {
102        return  mockMvc.perform(get("/task/{taskId}",
103                Tasks.WriteExampleApp.ID
104        ));
105    }
106}

Fifth, we have to ensure that the shown task has one tag. After we have written this integration test, the relevant part 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.hamcrest.Matchers.*;
23
24import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
25import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
26
27@RunWith(SpringJUnit4ClassRunner.class)
28@ContextConfiguration(classes = {IntegrationTestContext.class})
29@WebAppConfiguration
30@TestExecutionListeners({
31        DependencyInjectionTestExecutionListener.class,
32        TransactionalTestExecutionListener.class,
33        DbUnitTestExecutionListener.class,
34        ServletTestExecutionListener.class
35})
36@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
37@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
38@Category(IntegrationTest.class)
39@ActiveProfiles(Profiles.INTEGRATION_TEST)
40public class ShowTaskWhenTaskIsFoundTest {
41
42    @Autowired
43    private WebApplicationContext webAppContext;
44
45    private MockMvc mockMvc;
46
47    @Before
48    public void configureSystemUnderTest() {
49        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
50                .build();
51    }
52
53    @Test
54    public void shouldShowOneTagOfFoundTask() throws Exception {
55        openShowTaskPage()
56                .andExpect(model().attribute("task",
57                        hasProperty("tags", hasSize(1))
58                ));
59    }
60
61    private ResultActions openShowTaskPage() throws Exception {
62        return  mockMvc.perform(get("/task/{taskId}",
63                Tasks.WriteExampleApp.ID
64        ));
65    }
66}

Sixth, we have to verify that the tested controller method shows the information of the found tag. After we have written this integration test, 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.hamcrest.Matchers.*;
23import static org.hamcrest.Matchers.contains;
24import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
25import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
26
27@RunWith(SpringJUnit4ClassRunner.class)
28@ContextConfiguration(classes = {IntegrationTestContext.class})
29@WebAppConfiguration
30@TestExecutionListeners({
31        DependencyInjectionTestExecutionListener.class,
32        TransactionalTestExecutionListener.class,
33        DbUnitTestExecutionListener.class,
34        ServletTestExecutionListener.class
35})
36@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
37@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
38@Category(IntegrationTest.class)
39@ActiveProfiles(Profiles.INTEGRATION_TEST)
40public class ShowTaskWhenTaskIsFoundTest {
41
42    @Autowired
43    private WebApplicationContext webAppContext;
44
45    private MockMvc mockMvc;
46
47    @Before
48    public void configureSystemUnderTest() {
49        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
50                .build();
51    }
52
53    @Test
54    public void shouldShowFoundTag() throws Exception {
55        openShowTaskPage()
56                .andExpect(model().attribute("task",
57                     hasProperty("tags", contains(
58                         allOf(
59                             hasProperty("id",
60                                 is(Tasks.WriteExampleApp.Tags.Example.ID)
61                             ),
62                             hasProperty("name",
63                                 is(Tasks.WriteExampleApp.Tags.Example.NAME)
64                             )
65                         )
66                     ))
67                ));
68    }
69
70    private ResultActions openShowTaskPage() throws Exception {
71        return  mockMvc.perform(get("/task/{taskId}",
72                Tasks.WriteExampleApp.ID
73        ));
74    }
75}

Next, we will write integration tests for a controller method that searches tasks from the database.

Use Case 2: Searching Tasks

Introduction to System Under Test

We have to write integration tests for a controller method that processes POST requests send to the path: ‘/task/search’. This method is method called: showSearchResults() and it is implemented by following these steps:

  1. Get the used search term from the request parameter called: searchTerm.
  2. Find the search results from the database.
  3. Put the search results to a model attribute called: tasks.
  4. Return the name of the view (’task/search-results’) that renders the search results.

The source code of the tested controller method looks as follows:

 1import org.springframework.beans.factory.annotation.Autowired;
 2import org.springframework.stereotype.Controller;
 3import org.springframework.ui.Model;
 4import org.springframework.web.bind.annotation.RequestMapping;
 5import org.springframework.web.bind.annotation.RequestMethod;
 6import org.springframework.web.bind.annotation.RequestParam;
 7
 8import java.util.List;
 9
10@Controller
11public class TaskSearchController {
12
13    private final TaskSearchService service;
14
15    @Autowired
16    TaskSearchController(TaskSearchService service) {
17        this.service = service;
18    }
19
20    @RequestMapping(value = "task/search", method = RequestMethod.POST)
21    public String showSearchResults(@RequestParam("searchTerm") String searchTerm,
22                                    Model model) {
23        List<TaskListDTO> searchResults = service.search(searchTerm);
24        model.addAttribute("tasks", searchResults);
25        return "task/search-results";
26    }
27}

The TaskListDTO is a DTO class that contains the information of a single task which is shown on the search results page. Its source code looks as follows:

1public class TaskListDTO {
2
3    private Long id;
4    private String title;
5    private TaskStatus status;
6
7	//Getters and setters are omitted
8}

Next, we will write integration tests which ensure that the showSearchResults() method is working as expected when one task is found.

Writing Our Integration Tests

Before we can write the actual integration tests, we have to add test specific configuration into our test class. We can configure our test cases by following these steps:

  1. Configure the DbUnit data set that initializes our database into a known state. Because we are writing integration tests for a finder method, all test methods can use the same data set. Also, we will use the DbUnit data set (tasks.xml) that we used when we wrote integration tests for the showTask() method.
  2. Create a private method that sends a POST request to the path: ‘/task/search’ and specifies the used search term. This method must return a ResultActions object.

After we have configured our test cases, 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.Before;
 5import org.junit.experimental.categories.Category;
 6import org.junit.runner.RunWith;
 7import org.springframework.beans.factory.annotation.Autowired;
 8import org.springframework.test.context.ActiveProfiles;
 9import org.springframework.test.context.ContextConfiguration;
10import org.springframework.test.context.TestExecutionListeners;
11import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
12import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
13import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
14import org.springframework.test.context.web.ServletTestExecutionListener;
15import org.springframework.test.context.web.WebAppConfiguration;
16import org.springframework.test.web.servlet.MockMvc;
17import org.springframework.test.web.servlet.ResultActions;
18import org.springframework.test.web.servlet.setup.MockMvcBuilders;
19import org.springframework.web.context.WebApplicationContext;
20
21import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
22
23@RunWith(SpringJUnit4ClassRunner.class)
24@ContextConfiguration(classes = {IntegrationTestContext.class})
25@WebAppConfiguration
26@TestExecutionListeners({
27        DependencyInjectionTestExecutionListener.class,
28        TransactionalTestExecutionListener.class,
29        DbUnitTestExecutionListener.class,
30        ServletTestExecutionListener.class
31})
32@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
33@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
34@Category(IntegrationTest.class)
35@ActiveProfiles(Profiles.INTEGRATION_TEST)
36public class SearchWhenOneTaskIsFound {
37
38    @Autowired
39    private WebApplicationContext webAppContext;
40
41    private MockMvc mockMvc;
42
43    @Before
44    public void configureSystemUnderTest() {
45        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
46                .build();
47    }
48
49    private ResultActions submitSearchForm() throws Exception {
50        return mockMvc.perform(post("/task/search")
51                .param("searchTerm", Tasks.SEARCH_TERM_ONE_MATCH)
52        );
53    }
54}

After we have configured our test cases, we have to write five integration tests for the showSearchResults() method.

First, we have to verify that the tested method returns the HTTP status code 200. After we have written this integration test, 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
23import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
24
25@RunWith(SpringJUnit4ClassRunner.class)
26@ContextConfiguration(classes = {IntegrationTestContext.class})
27@WebAppConfiguration
28@TestExecutionListeners({
29        DependencyInjectionTestExecutionListener.class,
30        TransactionalTestExecutionListener.class,
31        DbUnitTestExecutionListener.class,
32        ServletTestExecutionListener.class
33})
34@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
35@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
36@Category(IntegrationTest.class)
37@ActiveProfiles(Profiles.INTEGRATION_TEST)
38public class SearchWhenOneTaskIsFound {
39
40    @Autowired
41    private WebApplicationContext webAppContext;
42
43    private MockMvc mockMvc;
44
45    @Before
46    public void configureSystemUnderTest() {
47        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
48                .build();
49    }
50
51    @Test
52    public void shouldReturnHttpStatusCodeOk() throws Exception {
53        submitSearchForm()
54                .andExpect(status().isOk());
55    }
56
57    private ResultActions submitSearchForm() throws Exception {
58        return mockMvc.perform(post("/task/search")
59                .param("searchTerm", Tasks.SEARCH_TERM_ONE_MATCH)
60        );
61    }
62}

Second, we have to verify that the tested controller method renders the show search results view (’task/search-results’). After we have written this integration test, the relevant part of our integration test class looks as follows:

 1import com.github.springtestdbunit.DbUnitTestExecutionListener;
 2import com.github.springtestdbunit.annotation.DatabaseSetup;
 3import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 4import com.testwithspring.intermediate.IntegrationTest;
 5import com.testwithspring.intermediate.IntegrationTestContext;
 6import com.testwithspring.intermediate.ReplacementDataSetLoader;
 7import com.testwithspring.intermediate.Tasks;
 8import com.testwithspring.intermediate.config.Profiles;
 9import org.junit.Before;
10import org.junit.Test;
11import org.junit.experimental.categories.Category;
12import org.junit.runner.RunWith;
13import org.springframework.beans.factory.annotation.Autowired;
14import org.springframework.test.context.ActiveProfiles;
15import org.springframework.test.context.ContextConfiguration;
16import org.springframework.test.context.TestExecutionListeners;
17import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
18import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
19import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
20import org.springframework.test.context.web.ServletTestExecutionListener;
21import org.springframework.test.context.web.WebAppConfiguration;
22import org.springframework.test.web.servlet.MockMvc;
23import org.springframework.test.web.servlet.ResultActions;
24import org.springframework.test.web.servlet.setup.MockMvcBuilders;
25import org.springframework.web.context.WebApplicationContext;
26
27import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
28import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
29
30@RunWith(SpringJUnit4ClassRunner.class)
31@ContextConfiguration(classes = {IntegrationTestContext.class})
32@WebAppConfiguration
33@TestExecutionListeners({
34        DependencyInjectionTestExecutionListener.class,
35        TransactionalTestExecutionListener.class,
36        DbUnitTestExecutionListener.class,
37        ServletTestExecutionListener.class
38})
39@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
40@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
41@Category(IntegrationTest.class)
42@ActiveProfiles(Profiles.INTEGRATION_TEST)
43public class SearchWhenOneTaskIsFound {
44
45    @Autowired
46    private WebApplicationContext webAppContext;
47
48    private MockMvc mockMvc;
49
50    @Before
51    public void configureSystemUnderTest() {
52        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
53                .build();
54    }
55
56    @Test
57    public void shouldRenderSearchResultView() throws Exception {
58        submitSearchForm()
59                .andExpect(view().name("task/search-results"));
60    }
61
62    private ResultActions submitSearchForm() throws Exception {
63        return mockMvc.perform(post("/task/search")
64                .param("searchTerm", Tasks.SEARCH_TERM_ONE_MATCH)
65        );
66    }
67}

Third, we have to ensure that the showSearchResults() method forwards the user to the show search results page. After we have implemented this test method, the relevant part of our integration 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
23import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
24
25@RunWith(SpringJUnit4ClassRunner.class)
26@ContextConfiguration(classes = {IntegrationTestContext.class})
27@WebAppConfiguration
28@TestExecutionListeners({
29        DependencyInjectionTestExecutionListener.class,
30        TransactionalTestExecutionListener.class,
31        DbUnitTestExecutionListener.class,
32        ServletTestExecutionListener.class
33})
34@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
35@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
36@Category(IntegrationTest.class)
37@ActiveProfiles(Profiles.INTEGRATION_TEST)
38public class SearchWhenOneTaskIsFound {
39
40    @Autowired
41    private WebApplicationContext webAppContext;
42
43    private MockMvc mockMvc;
44
45    @Before
46    public void configureSystemUnderTest() {
47        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
48                .build();
49    }
50
51    @Test
52    public void shouldForwardUserToSearchResultPageUrl() throws Exception {
53        submitSearchForm()
54                .andExpect(forwardedUrl("/WEB-INF/jsp/task/search-results.jsp"));
55    }
56
57    private ResultActions submitSearchForm() throws Exception {
58        return mockMvc.perform(post("/task/search")
59                .param("searchTerm", Tasks.SEARCH_TERM_ONE_MATCH)
60        );
61    }
62}
Again, if we are not using JSP views, we cannot write this integration test because the controller method doesn’t forward the user to the view search results page. Instead, it will read the content of the view from the template file and return the content of the rendered view in the response body.

Fourth, we have to ensure that the tested controller method shows the information of one task. After we have written this test, the relevant part of our integration 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.hamcrest.Matchers.hasSize;
23import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
24import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
25
26@RunWith(SpringJUnit4ClassRunner.class)
27@ContextConfiguration(classes = {IntegrationTestContext.class})
28@WebAppConfiguration
29@TestExecutionListeners({
30        DependencyInjectionTestExecutionListener.class,
31        TransactionalTestExecutionListener.class,
32        DbUnitTestExecutionListener.class,
33        ServletTestExecutionListener.class
34})
35@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
36@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
37@Category(IntegrationTest.class)
38@ActiveProfiles(Profiles.INTEGRATION_TEST)
39public class SearchWhenOneTaskIsFound {
40
41    @Autowired
42    private WebApplicationContext webAppContext;
43
44    private MockMvc mockMvc;
45
46    @Before
47    public void configureSystemUnderTest() {
48        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
49                .build();
50    }
51
52    @Test
53    public void shouldShowOneTask() throws Exception {
54        submitSearchForm()
55                .andExpect(model().attribute("tasks", hasSize(1)));
56    }
57
58    private ResultActions submitSearchForm() throws Exception {
59        return mockMvc.perform(post("/task/search")
60                .param("searchTerm", Tasks.SEARCH_TERM_ONE_MATCH)
61        );
62    }
63}

Fifth, we have to verify that the tested method shows the information of the correct task. After we have implemented this test method, the relevant part 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.Before;
 5import org.junit.Test;
 6import org.junit.experimental.categories.Category;
 7import org.junit.runner.RunWith;
 8import org.springframework.beans.factory.annotation.Autowired;
 9import org.springframework.test.context.ActiveProfiles;
10import org.springframework.test.context.ContextConfiguration;
11import org.springframework.test.context.TestExecutionListeners;
12import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
14import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
15import org.springframework.test.context.web.ServletTestExecutionListener;
16import org.springframework.test.context.web.WebAppConfiguration;
17import org.springframework.test.web.servlet.MockMvc;
18import org.springframework.test.web.servlet.ResultActions;
19import org.springframework.test.web.servlet.setup.MockMvcBuilders;
20import org.springframework.web.context.WebApplicationContext;
21
22import static org.hamcrest.Matchers.*;
23import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
24import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
25
26@RunWith(SpringJUnit4ClassRunner.class)
27@ContextConfiguration(classes = {IntegrationTestContext.class})
28@WebAppConfiguration
29@TestExecutionListeners({
30        DependencyInjectionTestExecutionListener.class,
31        TransactionalTestExecutionListener.class,
32        DbUnitTestExecutionListener.class,
33        ServletTestExecutionListener.class
34})
35@DatabaseSetup("/com/testwithspring/intermediate/tasks.xml")
36@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
37@Category(IntegrationTest.class)
38@ActiveProfiles(Profiles.INTEGRATION_TEST)
39public class SearchWhenOneTaskIsFound {
40
41    @Autowired
42    private WebApplicationContext webAppContext;
43
44    private MockMvc mockMvc;
45
46    @Before
47    public void configureSystemUnderTest() {
48        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
49                .build();
50    }
51
52    @Test
53    public void shouldShowCorrectTask() throws Exception {
54        submitSearchForm()
55                .andExpect(model().attribute("tasks", hasItem(allOf(
56                        hasProperty("id", is(Tasks.WriteLesson.ID)),
57                        hasProperty("title", is(Tasks.WriteLesson.TITLE)),
58                        hasProperty("status", is(Tasks.WriteLesson.STATUS))
59                ))));
60    }
61
62    private ResultActions submitSearchForm() throws Exception {
63        return mockMvc.perform(post("/task/search")
64                .param("searchTerm", Tasks.SEARCH_TERM_ONE_MATCH)
65        );
66    }
67}

We have now written integration tests for two different controller methods that render information found from the database. Let’s summarize what we learned from this lesson.

Summary

This lesson has taught us three things:

  • It’s a good idea to use the same data set when we are writing integration tests for controllers and repositories that find information from the database.
  • We can support multiple time zones by making sure that the created test data uses the system’s default time zone.
  • We can reduce duplicate code by writing helper methods that create HTTP requests and send the created requests to the tested controller methods.

Get the source code from Github