Search code examples
javagroovygradlespring-bootspock

How to start Spring Boot app in Spock Integration Test


What is the best way to run an integration test (e.g., @IntegrationTest) with Spock? I would like to bootstrap the whole Spring Boot application and execute some HTTP calls to test the whole functionality.

Spring Boot app starts in this working JUnit test (first the app runs and then the tests execute):

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyServer.class)
@WebAppConfiguration
@IntegrationTest
class MyTest {
   RestTemplate template = new TestRestTemplate();

   @Test
   public void testDataRoutingWebSocketToHttp() {
      def a = template.getForEntity("http://localhost:8080", String.class)
      println a
   }
}

But with Spock the application doesn't start (how can I get it to start?):

@SpringApplicationConfiguration(classes = MyServer.class)
@WebAppConfiguration
@IntegrationTest
class MyTestSpec extends Specification {

   RestTemplate template = new TestRestTemplate();

   def "Do my test"() {
      setup:
      def a = template.getForEntity("http://localhost:8080", String.class)

      expect:
      println a
   }
}

For Spock, of course, I have specified the proper dependencies in my Gradle build file:

...
dependencies {
   testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
   testCompile 'org.spockframework:spock-spring:0.7-groovy-2.0'
}
...

Solution

  • The problem is that Spock Spring is looking for Spring's @ContextConfiguration annotation and doesn't manage to find it. Strictly speaking MyTestSpec is annotated with @ContextConfiguration as it's a meta-annotation on @SpringApplicationConfiguration but Spock Spring doesn't consider meta-annotations as part of its search. There's an issue to address this limitation. In the meantime you can work around it.

    All that @SpringApplicationConfiguration is doing is customising @ContextConfiguration with a Boot-specific context loader. This means that you can achieve the same effect by using an appropriately configured @ContextConfiguration annotation instead:

    @ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = MyServer.class)
    @WebAppConfiguration
    @IntegrationTest
    class MyTestSpec extends Specification {
        …
    }
    

    Update: Just to make sure it's clear (and based on the comments, it wasn't), for this to work you need to have org.spockframework:spock-spring on the classpath.