Подтвердить что ты не робот

Тест интеграции с Spring Boot и Spock

Каков наилучший способ запуска теста интеграции (например, @IntegrationTest) со Spock? Я хотел бы загрузить загрузочное приложение Spring и выполнить некоторые 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'
}
...

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

4b9b3361

Ответ 1

Проблема заключается в том, что 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 в пути к классам.

Ответ 2

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

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

Если вы комбинируете @TestConfiguration с новым Spock DetachedMockFactory, тогда у вас есть все компоненты, которые вам нужно будет вставить Spock Mocks в ваш контекст Spring.

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

UPDATE Существует PR, чтобы получить дополнительную поддержку в Spock для инъекции Spock Mocks в контекст Spring для тестирования интеграции. Новые @SpringBean и @SpringSpy будут похожи на аннотации @MockBean и @SpyBean

Ответ 3

В новой Spring загрузочной версии (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/

Ответ 4

Вот настройка, которая запускает загрузку, а затем запускает тесты 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"
}