使用弹簧靴和 Spock 进行集成测试

2022-09-01 03:07:24

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

我可以使用JUnit做到这一点(首先运行应用程序,然后执行测试):

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

我错过了什么吗?


答案 1

问题是Spock Spring正在寻找Spring的注释,但无法找到它。严格来说,它是一个元注释,但Spock Spring并不认为元注释是其搜索的一部分。存在解决此限制的问题。在此期间,您可以解决它。@ContextConfigurationMyTestSpec@ContextConfiguration@SpringApplicationConfiguration

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

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

更新:只是为了确保它是清晰的(并且根据注释,它不是),为了在类路径上工作,你需要有这个。org.spockframework:spock-spring


答案 2

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

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

如果您与新的Spock结合使用,那么您就拥有了将Spock Mocks注入Spring上下文所需的所有组件。@TestConfigurationDetachedMockFactory

我有一篇博客文章,其中包含示例代码:使用Spock Mocks进行Spring Integration Testing

快速和肮脏是这个

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

更新一个PR可以在Spock中获得更多的原生支持,以便将Spock Mocks注入Spring上下文以进行集成测试。新的 和 会像 和 注释@SpringBean@SpringSpy@MockBean@SpyBean

更新Spock 1.2 现在应该包括这些更改。在文档更新之前,以下是Spock 1.2 Spring Integration Test注释的预览


推荐