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.

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-spring dependency must be the same as the version of the spock-core dependency.
  • If we are using Spring Boot, we can override the spock-core and spock-spring versions by setting the value of the spock.version property.

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:

  1. Configure the application context configuration class or XML configuration file that configures the application context of our integration tests.
  2. If the loaded ApplicationContext is an instance of the WebApplicationContext class, we have to annotate our specification class with the @WebAppConfiguration annotation.
  3. If we are using DbUnit, we have to register a test execution listener called DbUnitTestExecutionListener and ensure that this test execution listener is merged with the default test execution listeners.
  4. If we want to override the DbUnit configuration, we have to annotate our specification class with the @DbUnitConfiguration annotation. Let’s ensure that our DbUnit data sets are loaded by the ReplacementDataSetLoader class.
  5. 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}
As we can see, when we are writing integration tests with Spock Framework, we don’t have to configure the runner (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:

  1. Inject the loaded WebApplicationContext into our specification class.
  2. Add a new instance field to our specification class. This field contains the MockMvc object that we use when we write integration tests for the system under specification.
  3. Add the setup() method to our specification class.
  4. Create a new MockMvc object by using the web application context based configuration and store the created object in the mockMvc field.

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:

  1. Remove the code that creates a new MockMvc object.
  2. Remove the @ContextConfiguration and @WebAppConfiguration annotations.
  3. Annotate the specification class with the @SpringBootTest annotation. 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:

  1. Enable the auto configuration of the Spring MVC Test framework.
  2. Inject the MockMvc bean 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-spring module integrates Spring Test Framework with Spock Framework.
  • The version of the spock-spring dependency must be the same as the version of the spock-core dependency.
  • When we are writing integration tests with Spock Framework, we don’t have to configure the runner that runs our integration tests.

Get the source code from Github