webentwicklung-frage-antwort-db.com.de

Integrationstest mit Spring Boot und Spock

Was ist der beste Weg, um einen Integrationstest durchzuführen (z. B. @IntegrationTest ) mit Spock? Ich möchte bootstrap die gesamte Spring Boot-Anwendung und einige HTTP-Aufrufe ausführen, um die gesamte Funktionalität zu testen.

Ich kann es mit JUnit machen (zuerst läuft die App und dann werden die Tests ausgeführt):

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

Aber mit Spock startet die Anwendung nicht:

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

Für Spock habe ich natürlich die richtigen Abhängigkeiten in meiner Gradle-Build-Datei angegeben:

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

Vermisse ich etwas?

36
kuceram

Das Problem ist, dass Spock Spring nach der Annotation @ContextConfiguration Von Spring sucht und diese nicht findet. Genau genommen ist MyTestSpec is mit @ContextConfiguration Kommentiert, da es sich um eine Meta-Annotation auf @SpringApplicationConfiguration Handelt, aber Spock Spring betrachtet Meta-Annotationen nicht als Teil seiner Suche. Es gibt ein Problem , um diese Einschränkung zu beheben. In der Zwischenzeit können Sie es umgehen.

Alles, was @SpringApplicationConfiguration Tut, ist das Anpassen von @ContextConfiguration Mit einem bootspezifischen Kontextlader. Dies bedeutet, dass Sie denselben Effekt erzielen können, indem Sie stattdessen eine entsprechend konfigurierte Annotation @ContextConfiguration Verwenden:

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

Update: Nur um sicherzugehen, dass es klar ist (und laut Kommentaren auch nicht), muss org.spockframework:spock-spring Auf dem Klassenpfad.

49
Andy Wilkinson

Idealerweise verwenden Sie Spring Boot 1.4+ und Spock 1.1+.

Spring Boot hat viele nützliche Anmerkungen hinzugefügt. Zusätzlich zu dem @SpringBootTest, Den @ ignacio.suay erwähnte, wurde auch @TestConfiguration Hinzugefügt, was nützlich ist, wenn Sie Spring-Mocks in Ihren Integrationstests anstelle von Mockito verwenden möchten.

Wenn Sie @TestConfiguration Mit dem neuen Spock DetachedMockFactory kombinieren, haben Sie alle Komponenten, die Sie benötigen, um Spock Mocks in Ihren Spring-Kontext einzufügen.

Ich habe hier einen Blog-Beitrag mit Beispielcode: Spring Integration Testing with Spock Mocks .

Das schnelle und schmutzige ist das

@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 [~ # ~] Es gibt einen PR , um mehr native Unterstützung für das Injizieren von Spock in Spock zu erhalten Fügt sich in den Spring-Kontext für Integrationstests ein. Die neuen Annotationen @SpringBean Und @SpringSpy Entsprechen den Annotationen @MockBean Und @SpyBean

[~ # ~] Update [~ # ~] Spock 1.2 sollte nun diese Änderungen enthalten. Bis die Dokumentation aktualisiert wird, ist hier ein Vorschau der Spock 1.2-Anmerkungen für Spring Integration Testing .

8
Snekse

In der neuen Spring Boot-Version (1.4) anstelle von:

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

Du könntest benutzen

@SpringBootTest(classes = MyServer.class)

und Sie können den Anwendungskontext starten und alle Abhängigkeiten festlegen.

weitere Informationen finden Sie in diesem Beispiel: http://ignaciosuay.com/how-to-do-integration-tests-with-spring-boot-and-spock/

3
ignacio.suay

Hier ist ein Setup, das die Boot-Anwendung startet und dann Spock-Tests ausführt:

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

Und denken Sie daran, Abhängigkeiten zu spock und groovy innerhalb von build.gradle Hinzuzufügen.

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