使用Spring Boot和Spock进行集成测试

时间:2014-06-25 10:04:49

标签: java groovy gradle spring-boot spock

使用Spock运行集成测试(例如@IntegrationTest)的最佳方法是什么?我想引导整个Spring Boot应用程序并执行一些HTTP调用来测试整个功能。

我可以使用JUnit(首先运行app然后执行测试):

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

但是使用Spock,应用程序无法启动:

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

对于Spock,当然,我在Gradle构建文件中指定了正确的依赖项:

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

我错过了什么吗?

4 个答案:

答案 0 :(得分:48)

问题是Spock Spring正在寻找Spring的@ContextConfiguration注释而无法找到它。严格来说,MyTestSpec @ContextConfiguration进行注释,因为它是@SpringApplicationConfiguration上的元注释,但Spock Spring并未将元注释视为其搜索的一部分。有一个issue来解决这个限制。与此同时,你可以解决它。

@SpringApplicationConfiguration所做的就是使用特定于引导的上下文加载器自定义@ContextConfiguration。这意味着您可以通过使用适当配置的@ContextConfiguration注释来实现相同的效果:

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

更新:只是为了确保它是明确的(并且根据评论,它不是),为此,您需要在类路径上使用org.spockframework:spock-spring

答案 1 :(得分:8)

理想情况下,您将使用Spring Boot 1.4+和Spock 1.1+。

Spring Boot添加了许多有用的注释。除了@ ignacio.suay提到的@SpringBootTest之外,他们还添加了@TestConfiguration,如果你想在集成测试中使用Spring模拟而不是Mockito,那么它很有用。

如果你将@TestConfiguration与新的Spock DetachedMockFactory结合使用,那么你就拥有了将Spock Mocks注入Spring环境所需的所有组件。

我的博客帖子中包含示例代码:Spring Integration Testing with Spock Mocks

快速而肮脏的是这个

@SpringBootTest
class MyIntegrationTest extends Specification {

  @Autowired ExternalRankingService externalRankingServiceMock

  def "GetRank"() {
    when:
    classUnderTest.getRankFor('Bob')

    then:
    1 * externalRankingServiceMock.fetchRank('Bob') >> 5

  }

  @TestConfiguration
  static class Config {
    private DetachedMockFactory factory = new DetachedMockFactory()

    @Bean
    ExternalRankingService externalRankingService() {
      factory.Mock(ExternalRankingService)
    }
  }
}

<强>更新a PR可以在Spock中获得更多本机支持,以便将Spock Mocks注入到Spring环境中进行集成测试。新@SpringBean@SpringSpy@MockBean@SpyBean注释相似

<强>更新 Spock 1.2现在应该包含这些更改。在文档更新之前,这里是preview of the Spock 1.2 Annotations for Spring Integration Testing

答案 2 :(得分:3)

在新的Spring Boot版本(1.4)中,而不是使用:

@SpringApplicationConfiguration(classes = MyServer.class)
@WebAppConfiguration
@IntegrationTest

您可以使用

@SpringBootTest(classes = MyServer.class)

您将能够启动应用程序上下文并设置任何依赖项。

有关详细信息,请查看此示例: http://ignaciosuay.com/how-to-do-integration-tests-with-spring-boot-and-spock/

答案 3 :(得分:0)

这是一个启动启动应用程序然后运行spock测试的设置:

class HelloControllerSpec extends Specification {

@Shared
@AutoCleanup
ConfigurableApplicationContext context

void setupSpec() {
    Future future = Executors
            .newSingleThreadExecutor().submit(
            new Callable() {
                @Override
                public ConfigurableApplicationContext call() throws Exception {
                    return (ConfigurableApplicationContext) SpringApplication
                            .run(Application.class)
                }
            })
    context = future.get(60, TimeUnit.SECONDS)
}

void "should return pong from /ping"() {
    when:
    ResponseEntity entity = new RestTemplate().getForEntity("http://localhost:8080/ping", String.class)

    then:
    entity.statusCode == HttpStatus.OK
    entity.body == 'pong'
}
}

请记住在build.gradle

中添加依赖关系到spock和groovy
dependencies {
    // other dependencies
    testCompile "org.codehaus.groovy:groovy-all:2.2.0"
    testCompile "org.spockframework:spock-core:0.7-groovy-2.0"
}