Configuring the System Under Specification
After we have finished this lesson, we:
- Can get the required dependencies with Maven and Gradle.
- Know how we can configure the system under specification when we are using Spring Framework or Spring Boot.
This lesson assumes that:
Getting the Required Dependencies
Before we can write integration tests for our Spring or Spring Boot application, we have to declare the spock-spring dependency in our build script. This dependency integrates Spring Test Framework with Spock Framework.
If we are using Maven, we have to add the following snippet to our POM file:
1<dependency>
2 <groupId>org.spockframework</groupId>
3 <artifactId>spock-spring</artifactId>
4 <version>1.1-groovy-2.4</version>
5 <scope>test</scope>
6</dependency>
If we are using Gradle, we have to add the following snippet to our build.gradle file:
1integrationTestCompile(
2 'org.spockframework:spock-spring:1.1-groovy-2.4'
3)
There are two things I want to point out before we can continue this lesson:
- The version of the
spock-springdependency must be the same as the version of thespock-coredependency. - If we are using Spring Boot, we can override the
spock-coreandspock-springversions by setting the value of thespock.versionproperty.
Next, we will find out how we can configure the system under specification when we are writing integration tests for Spring web applications.
Writing Integration Tests for Spring (Web) Applications
When we are using Spring Framework, we can configure the system under specification by following these steps:
- Configure the application context configuration class or XML configuration file that configures the application context of our integration tests.
- If the loaded
ApplicationContextis an instance of theWebApplicationContextclass, we have to annotate our specification class with the@WebAppConfigurationannotation. - If we are using DbUnit, we have to register a test execution listener called
DbUnitTestExecutionListenerand ensure that this test execution listener is merged with the default test execution listeners. - If we want to override the DbUnit configuration, we have to annotate our specification class with the
@DbUnitConfigurationannotation. Let’s ensure that our DbUnit data sets are loaded by theReplacementDataSetLoaderclass. - Ensure that our integration tests are run by using the Spring profile called:
integrationTest.
After we have configured the system under specification, the source code of our specification class looks as follows:
1import com.github.springtestdbunit.DbUnitTestExecutionListener
2import com.github.springtestdbunit.annotation.DbUnitConfiguration
3import com.github.springtestdbunit.dataset.ReplacementDataSetLoader
4import org.junit.experimental.categories.Category
5import org.springframework.test.context.ActiveProfiles
6import org.springframework.test.context.ContextConfiguration
7import org.springframework.test.context.TestExecutionListeners
8import org.springframework.test.context.web.WebAppConfiguration
9import spock.lang.Specification
10
11@ContextConfiguration(classes = [IntegrationTestContext.class])
12@WebAppConfiguration
13@TestExecutionListeners(value = DbUnitTestExecutionListener.class,
14 mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
15)
16@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
17@Category(IntegrationTest.class)
18@ActiveProfiles(Profiles.INTEGRATION_TEST)
19class ExampleSpec extends Specification {
20
21}
SpringJunit4ClassRunner) that runs our integration tests.
If we don’t have to use the Spring MVC Test framework, we can simply inject the tested bean into our specification class. However, if we are writing integration tests for a Spring MVC controller, we have to configure the Spring MVC Test framework by following these steps:
- Inject the loaded
WebApplicationContextinto our specification class. - Add a new instance field to our specification class. This field contains the
MockMvcobject that we use when we write integration tests for the system under specification. - Add the
setup()method to our specification class. - Create a new
MockMvcobject by using the web application context based configuration and store the created object in themockMvcfield.
After we have configured the Spring MVC Test framework, the source code of our specification class looks as follows:
1import com.github.springtestdbunit.DbUnitTestExecutionListener
2import com.github.springtestdbunit.annotation.DbUnitConfiguration
3import com.github.springtestdbunit.dataset.ReplacementDataSetLoader
4import org.junit.experimental.categories.Category
5import org.springframework.beans.factory.annotation.Autowired
6import org.springframework.test.context.ActiveProfiles
7import org.springframework.test.context.ContextConfiguration
8import org.springframework.test.context.TestExecutionListeners
9import org.springframework.test.context.web.WebAppConfiguration
10import org.springframework.test.web.servlet.setup.MockMvcBuilders
11import org.springframework.web.context.WebApplicationContext
12import spock.lang.Specification
13
14import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity
15
16@ContextConfiguration(classes = [IntegrationTestContext.class])
17@WebAppConfiguration
18@TestExecutionListeners(value = DbUnitTestExecutionListener.class,
19 mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
20)
21@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
22@Category(IntegrationTest.class)
23@ActiveProfiles(Profiles.INTEGRATION_TEST)
24class ExampleSpec extends Specification {
25
26 @Autowired
27 WebApplicationContext webAppContext
28
29 def mockMvc
30
31 def setup() {
32 mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext)
33 .apply(springSecurity())
34 .build()
35 }
36}
Let’s move on and find out how we can configure the system under specification when we are writing integration tests for Spring Boot web applications.
Writing Integration Tests for Spring Boot (Web) Applications
When we are using Spring Boot, we can configure the system under specification by using the technique that was described in the previous section.
That being said, I think that we should take advantage of the Spring Boot specific features when we configure the system under specification because these features allow us to configure the system under specification without writing any boilerplate code.
We can use these features by making the following changes to our specification class:
- Remove the code that creates a new
MockMvcobject. - Remove the
@ContextConfigurationand@WebAppConfigurationannotations. - Annotate the specification class with the
@SpringBootTestannotation. Remember to configure the application context configuration class that configures the application context of our integration tests.
After we have configured the system under specification, the source code of our specification class looks as follows:
1import com.github.springtestdbunit.DbUnitTestExecutionListener
2import com.github.springtestdbunit.annotation.DbUnitConfiguration
3import com.github.springtestdbunit.dataset.ReplacementDataSetLoader
4import org.junit.experimental.categories.Category
5import org.springframework.boot.test.context.SpringBootTest
6import org.springframework.test.context.ActiveProfiles
7import org.springframework.test.context.TestExecutionListeners
8import spock.lang.Specification
9
10@SpringBootTest(classes = [IntegrationTestContext.class])
11@TestExecutionListeners(value = DbUnitTestExecutionListener.class,
12 mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
13)
14@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
15@Category(IntegrationTest.class)
16@ActiveProfiles(Profiles.INTEGRATION_TEST)
17class ExampleSpec extends Specification {
18
19}
If we don’t have to use the Spring MVC Test framework, we can simply inject the tested bean into our specification class. However, if we are writing integration tests for a Spring MVC controller, we have to configure the Spring MVC Test framework by following these steps:
- Enable the auto configuration of the Spring MVC Test framework.
- Inject the
MockMvcbean into our specification class.
After we have configured the Spring MVC Test framework, the source code of our specification class looks as follows:
1import com.github.springtestdbunit.DbUnitTestExecutionListener
2import com.github.springtestdbunit.annotation.DbUnitConfiguration
3import com.github.springtestdbunit.dataset.ReplacementDataSetLoader
4import org.springframework.beans.factory.annotation.Autowired
5import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
6import org.springframework.boot.test.context.SpringBootTest
7import org.springframework.test.context.ActiveProfiles
8import org.springframework.test.context.TestExecutionListeners
9import org.springframework.test.web.servlet.MockMvc
10import spock.lang.Specification
11
12@SpringBootTest(classes = [IntegrationTestContext.class])
13@AutoConfigureMockMvc
14@TestExecutionListeners(value = DbUnitTestExecutionListener.class,
15 mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
16)
17@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
18@Category(IntegrationTest.class)
19@ActiveProfiles(Profiles.INTEGRATION_TEST)
20class ExampleSpec extends Specification {
21
22 @Autowired
23 MockMvc mockMvc
24}
We can now configure the system under specification when we are writing integration tests for Spring and Spring Boot web applications. Let’s summarize what we learned from this lesson.
Summary
This lesson has taught us three things:
- The
spock-springmodule integrates Spring Test Framework with Spock Framework. - The version of the
spock-springdependency must be the same as the version of thespock-coredependency. - When we are writing integration tests with Spock Framework, we don’t have to configure the runner that runs our integration tests.