Интеграционный тест с Spring Boot и 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'
}
...

Я что-то пропустила?

4 ответов


проблема в том, что Спок Спринг ищет весну @ContextConfiguration аннотация и не удается ее найти. Строго говоря MyTestSpec и аннотируется @ContextConfiguration как это мета-аннотации @SpringApplicationConfiguration но Спок Спринг не рассматривает мета-аннотации как часть своего поиска. Есть вопрос для решения этого ограничения. А пока ты можешь обойти это.

все это @SpringApplicationConfiguration делает это настройка @ContextConfiguration С загрузкой загрузчик контекста. Это означает, что вы можете достичь того же эффекта с помощью правильно настроенный аннотация:

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

обновление: просто чтобы убедиться ,что это ясно (и на основе комментариев, это не было), для этого вам нужно иметь org.spockframework:spock-spring на пути к классу.


в идеале вы будете использовать Spring Boot 1.4+ и Spock 1.1+.

Spring Boot добавил много полезных аннотаций. В дополнение к этому @SpringBootTest это @ignacio.Суай упомянул, они также добавили @TestConfiguration что полезно, если вы хотите использовать Spring mocks в своих интеграционных тестах вместо Mockito.

если вы объедините @TestConfiguration С Новым Споком DetachedMockFactory, тогда у вас есть все компоненты, которые вам понадобятся, чтобы ввести Spock Mocks в ваш весенний контекст.

Я сообщение в блоге с примером кода здесь:весеннее интеграционное тестирование с помощью 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)
    }
  }
}

обновление Есть пиар чтобы получить более родную поддержку в Spock для инъекции Spock Mocks в весенний контекст для интеграционного тестирования. Новый @SpringBean и @SpringSpy как бы @MockBean и @SpyBean аннотации

обновление Спок 1.2 теперь внесенные изменения. Пока документация не будет обновлена, вот предварительный просмотр аннотаций Spock 1.2 для тестирования интеграции Spring .


в новой версии 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/


вот настройка, которая запускает загрузочное приложение, а затем запускает тесты 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'
}
}

и не забудьте добавить зависимости к spock и groovy внутри build.gradle

dependencies {
    // other dependencies
    testCompile "org.codehaus.groovy:groovy-all:2.2.0"
    testCompile "org.spockframework:spock-core:0.7-groovy-2.0"
}