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?
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.
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 .
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/
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"
}