Test d'intégration avec Spring Boot et Spock

Quelle est la meilleure façon d'exécuter un test d'intégration (p. ex., @IntegrationTest) avec Spock? Je voudrais démarrer toute L'application Spring Boot et exécuter des appels HTTP pour tester toute la fonctionnalité.

Je peux le faire avec JUnit (d'abord l'application s'exécute, puis les tests exécuter):

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

Mais avec Spock l'application ne démarre pas:

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

Pour Spock, bien sûr, j'ai spécifié les dépendances appropriées dans mon fichier de construction Gradle:

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

Suis-je absent quelque chose?

33
demandé sur kuporific 2014-06-25 14:04:49

4 réponses

Le problème est que Spock Spring recherche l'annotation @ContextConfiguration de Spring et ne parvient pas à la trouver. Strictement parlant MyTestSpec est annoté avec @ContextConfiguration car c'est une méta-annotation sur @SpringApplicationConfiguration mais Spock Spring ne considère pas les méta-annotations dans le cadre de sa recherche. Il y a un problème pour résoudre cette limitation. En attendant, vous pouvez le contourner.

Tout ce que @SpringApplicationConfiguration fait est de personnaliser @ContextConfiguration avec un chargeur de contexte spécifique au démarrage. Cela signifie que vous pouvez obtenez le même effet en utilisant une annotation @ContextConfiguration correctement configurée à la place:

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

Update: juste pour s'assurer que c'est clair (et basé sur les commentaires, Ce n'était pas le cas), pour que cela fonctionne, vous devez avoir org.spockframework:spock-spring sur le classpath.

47
répondu Andy Wilkinson 2014-07-10 10:02:35

Idéalement, vous utiliserez Spring Boot 1.4 + et Spock 1.1+.

Spring Boot a ajouté beaucoup d'annotations utiles. En plus de cela @SpringBootTest que @ ignacio.suay a mentionné, ils ont également ajouté @TestConfiguration ce qui est utile si vous voulez utiliser Spring mocks dans vos tests d'intégration au lieu de Mockito.

Si vous combinez @TestConfiguration avec le nouveau Spock DetachedMockFactory, Vous avez tous les composants dont vous aurez besoin pour injecter des Mocks Spock dans votre contexte Spring.

J'ai un article de blog avec un exemple de code ici: test D'intégration de printemps avec Spock Mocks .

Le rapide et sale est ceci

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

Mise à jour Il y a un PR pour obtenir plus de support natif dans Spock pour injecter des Mocks Spock dans le contexte Spring pour les tests d'intégration. Les nouveaux @SpringBean et @SpringSpy seraient comme les annotations @MockBean et @SpyBean

Mise à jour Spock 1.2 devrait maintenant inclure ces changements. Jusqu'à ce que la documentation soit mise à jour, voici un aperçu du Spock 1.2 Annotations pour les tests D'intégration de printemps .

6
répondu Snekse 2018-09-25 16:25:15

Dans la nouvelle version Spring Boot (1.4) au lieu d'utiliser:

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

Vous pouvez utiliser

@SpringBootTest(classes = MyServer.class)

Et vous pourrez démarrer le contexte de l'application et définir toute dépendance.

Pour plus d'informations, veuillez consulter cet exemple: http://ignaciosuay.com/how-to-do-integration-tests-with-spring-boot-and-spock/

3
répondu ignacio.suay 2017-01-23 17:54:47

Voici une configuration qui démarre l'application de démarrage, puis exécute les tests 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'
}
}

Et n'oubliez pas d'ajouter des dépendances à spock et groovy à l'intérieur de build.gradle

dependencies {
    // other dependencies
    testCompile "org.codehaus.groovy:groovy-all:2.2.0"
    testCompile "org.spockframework:spock-core:0.7-groovy-2.0"
}
0
répondu Marcin Szymczak 2017-06-19 06:53:46