Integration Test with Spring Boot and Spock

kuceram picture kuceram · Jun 25, 2014 · Viewed 29.6k times · Source

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.

I can do it with JUnit (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:

@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'
}
...

Am I missing something?

Answer

Andy Wilkinson picture Andy Wilkinson · Jun 25, 2014

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.