Quelle est la meilleure façon d'exécuter un test d'intégration (par exemple, @IntegrationTest
) avec Spock? Je voudrais bootstrap toute l'application Spring Boot et exécuter quelques appels HTTP pour tester toute la fonctionnalité.
Je peux le faire avec JUnit (d'abord l'application s'exécute, puis les tests s'exécutent):
@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 en train de manquer quelque chose?
Le problème est que Spock Spring recherche _ @ContextConfiguration
annotation et n'arrive pas à la trouver. À proprement parler 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 comme faisant partie de sa recherche. Il y a un problème pour résoudre cette limitation. En attendant, vous pouvez contourner ce problème.
Tout ça @SpringApplicationConfiguration
est en train de personnaliser @ContextConfiguration
avec un chargeur de contexte spécifique au démarrage. Cela signifie que vous pouvez obtenir le même effet en utilisant un _ correctement configuré @ContextConfiguration
annotation à la place:
@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = MyServer.class)
@WebAppConfiguration
@IntegrationTest
class MyTestSpec extends Specification {
…
}
Mise à jour: Juste pour être sûr que c'est clair (et sur la base des commentaires, ce n'était pas le cas), pour que cela fonctionne, vous devez avoir org.spockframework:spock-spring
sur le chemin de classe.
Idéalement, vous utiliserez Spring Boot 1.4+ et Spock 1.1+.
Spring Boot a ajouté de nombreuses annotations utiles. En plus de ça @SpringBootTest
que @ ignacio.suay a mentionné, ils ont également ajouté @TestConfiguration
ce qui est utile si vous souhaitez utiliser Spring Mocks dans vos tests d'intégration au lieu de Mockito.
Si vous combinez @TestConfiguration
avec le nouveau Spock DetachedMockFactory
, vous disposez alors de tous les composants dont vous aurez besoin pour injecter Spock Mocks dans votre contexte Spring.
J'ai un article de blog avec un exemple de code ici: Spring Integration Testing with Spock Mocks .
Le rapide et sale est-ce
@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 n PR pour obtenir plus de support natif dans Spock pour l'injection de Spock Se moque dans le contexte Spring pour les tests d'intégration. Le nouveau @SpringBean
et @SpringSpy
serait comme le @MockBean
et @SpyBean
annotations
[~ # ~] mise à jour [~ # ~] Spock 1.2 devrait maintenant inclure ces changements. Jusqu'à la mise à jour de la documentation, voici un aperçu des annotations Spock 1.2 pour les tests d'intégration de Spring .
Dans la nouvelle version Spring Boot (1.4) au lieu d'utiliser:
@SpringApplicationConfiguration(classes = MyServer.class)
@WebAppConfiguration
@IntegrationTest
Vous pourriez utiliser
@SpringBootTest(classes = MyServer.class)
et vous pourrez démarrer le contexte de l'application et définir n'importe quelle 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 des 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 build.gradle
dependencies {
// other dependencies
testCompile "org.codehaus.groovy:groovy-all:2.2.0"
testCompile "org.spockframework:spock-core:0.7-groovy-2.0"
}