Java >> Java tutorial >  >> Tag >> maven

Integrationstest med Maven

1. Oversigt

Maven er det mest populære byggeværktøj i Java-området, mens integrationstest er en væsentlig del af udviklingsprocessen. Derfor er det et naturligt valg at konfigurere og udføre integrationstest med Maven.

I dette selvstudie gennemgår vi en række forskellige måder at bruge Maven til integrationstest og til at adskille integrationstest fra enhedstest.

2. Forberedelse

For at gøre demonstrationskoden tæt på et projekt i den virkelige verden opsætter vi en JAX-RS-applikation. Denne applikation implementeres på en server før udførelse af integrationstests og afmonteres efterfølgende.

2.1. Maven-konfiguration

Vi bygger vores REST-applikation omkring Jersey – referenceimplementeringen af ​​JAX-RS. Denne implementering kræver et par afhængigheder:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.27</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.27</version>
</dependency>

Vi kan finde de seneste versioner af disse afhængigheder her og her.

Vi bruger Jetty Maven-plugin'et til at konfigurere et testmiljø. Dette plugin starter en Jetty-server under præ-integrationstesten fase af Maven build-livscyklussen, og stopper den derefter i post-integration-testen fase.

Sådan konfigurerer vi Jetty Maven-plugin'et i pom.xml :

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.4.11.v20180605</version>
    <configuration>
        <httpConnector>
            <port>8999</port>
        </httpConnector>
        <stopKey>quit</stopKey>
        <stopPort>9000</stopPort>
    </configuration>
    <executions>
        <execution>
            <id>start-jetty</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>stop-jetty</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Når Jetty-serveren starter op, lytter den på port 8999 . stopNøglen og stopPort konfigurationselementer bruges udelukkende af pluginnets stop mål og deres værdi er ikke vigtigt fra vores perspektiv.

Her kan du finde den seneste version af Jetty Maven plugin.

En anden ting at bemærke er, at vi skal indstille emballagen element i pom.xml fil til war , ellers kan Jetty-plugin'et ikke starte serveren:

<packaging>war</packaging>

2.2. Oprettelse af en REST-applikation

Applikationens slutpunkt er meget simpelt – returnerer en velkomstbesked, når en GET-anmodning rammer kontekstroden:

@Path("/")
public class RestEndpoint {
    @GET
    public String hello() {
        return "Welcome to Baeldung!";
    }
}

Sådan registrerer vi slutpunktsklassen med Jersey:

package com.baeldung.maven.it;

import org.glassfish.jersey.server.ResourceConfig;

public class EndpointConfig extends ResourceConfig {
    public EndpointConfig() {
        register(RestEndpoint.class);
    }
}

For at få Jetty-serveren opmærksom på vores REST-applikation kan vi bruge en klassisk web.xml implementeringsbeskrivelse:

<web-app 
  xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">
    <servlet>
        <servlet-name>rest-servlet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.baeldung.maven.it.EndpointConfig</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>rest-servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Denne beskrivelse skal placeres i mappen /src/main/webapp /WEB-INF for at blive genkendt af serveren.

2.3. Testkode på klientsiden

Alle testklasser i de følgende afsnit indeholder en enkelt metode:

@Test
public void whenSendingGet_thenMessageIsReturned() throws IOException {
    String url = "http://localhost:8999";
    URLConnection connection = new URL(url).openConnection();
    try (InputStream response = connection.getInputStream();
      Scanner scanner = new Scanner(response)) {
        String responseBody = scanner.nextLine();
        assertEquals("Welcome to Baeldung!", responseBody);
    }
}

Som vi kan se, gør denne metode ikke andet end at sende en GET-anmodning til den webapplikation, vi konfigurerede før, og bekræfte svaret.

3. Integrationstest i aktion

En vigtig ting at bemærke ved integrationstest er, at testmetoder ofte tager ret lang tid at køre.

Som følge heraf bør vi udelukke integrationstest fra standard build-livscyklussen, hvilket forhindrer dem i at bremse hele processen, hver gang vi bygger et projekt.

En bekvem måde at adskille integrationstest på er at bruge build-profiler. Denne form for konfiguration gør det muligt for os kun at udføre integrationstest, når det er nødvendigt – ved at specificere en passende profil.

I de følgende afsnit konfigurerer vi alle integrationstest med build-profiler.

4. Test med Failsafe Plugin

Den nemmeste måde at køre integrationstest på er at bruge Maven failsafe plugin.

Som standard er Maven sikker plugin udfører enhedstest under testen fase, mens den fejlsikre plugin kører integrationstest i integration-testen fase .

Vi kan navngive testklasser med forskellige mønstre for disse plugins for at hente de vedlagte tests separat.

Standardnavnekonventionerne håndhæves af surefire og fejlsikker er forskellige, så vi skal blot følge disse konventioner for at adskille enheds- og integrationstests.

Udførelsen af ​​surefire plugin inkluderer alle klasser, hvis navn starter med Test , eller slutter med Test , Tests eller TestCase . I modsætning hertil er failsafe plugin udfører testmetoder i klasser, hvis navn starter med IT , eller slutter med IT eller ITCase .

Det er her, vi kan finde dokumentationen vedrørende testinkludering for surefire , og her er den til failsafe .

Lad os tilføje failsafe plugin til POM'en med standardkonfiguration:

<profile>
    <id>failsafe</id>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Dette link er hvor du kan finde den seneste version af failsafe plugin.

Med ovenstående konfiguration vil følgende testmetode blive udført i integrationstesten fase:

public class RestIT {
    // test method shown in subsection 2.3
}

Siden Jetty-serveren starter op i præ-integrationstesten fase og lukker ned i post-integration-test , testen vi lige har set bestået med denne kommando:

mvn verify -Pfailsafe

Vi kan også tilpasse navnemønstrene til at inkludere klasser med forskellige navne:

<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.22.0</version>
    <configuration>
        <includes>
            <include>**/*RestIT</include>
            <include>**/RestITCase</include>
        </includes>
    </configuration>
    ...
</plugin>

5. Test med Surefire-pluginnet

Bortset fra den fejlsikre plugin, kan vi også bruge surefire plugin til at udføre enheds- og integrationstests i forskellige faser.

Lad os antage, at vi vil navngive alle integrationstests med suffikset IntegrationTest . Siden den sikre plugin kører test med et sådant navn i testen fase som standard, skal vi ekskludere dem fra standardudførelsen:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <excludes>
            <exclude>**/*IntegrationTest</exclude>
        </excludes>
    </configuration>
</plugin>

Den seneste version af dette plugin er her.

Vi har taget alle testklasser med et navn, der slutter med IntegrationTest ud af byggelivscyklussen. Det er tid til at sætte dem tilbage med en profil:

<profile>
    <id>surefire</id>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <executions>
                    <execution>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                            <excludes>
                                <exclude>none</exclude>
                            </excludes>
                            <includes>
                                <include>**/*IntegrationTest</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

I stedet for at binde testen målet for sikkert plugin til testen byggefasen, som sædvanligt, bundede vi den til integrationstesten fase. Pluginnet starter så under integrationstestprocessen.

Bemærk, at vi skal angive en ekskludering element til ingen for at tilsidesætte den udelukkelse, der er angivet i basiskonfigurationen.

Lad os nu definere en integrationstestklasse med vores navngivningsmønster:

public class RestIntegrationTest {
    // test method shown in subsection 2.3
}

Denne test vil køre med kommandoen:

mvn verify -Psurefire

6. Test med Cargo Plugin

Vi kan bruge surefire plugin med Maven cargo plugin. Dette plugin kommer med indbygget understøttelse af indlejrede servere, som er meget nyttige til integrationstest.

Du kan finde flere oplysninger om denne kombination her.

7. Test med JUnit's @Category

En bekvem måde at selektivt udføre test på er at udnytte @Kategorien annotation i JUnit 4-rammen. Denne annotation lader os udelukke bestemte test fra enhedstestning og inkludere dem i integrationstest.

Først og fremmest har vi brug for en grænseflade eller klasse for at fungere som en kategoriidentifikator:

package com.baeldung.maven.it;

public interface Integration { }

Vi kan derefter dekorere en testklasse med @Category annotering og integration identifikator:

@Category(Integration.class)
public class RestJUnitTest {
    // test method shown in subsection 2.3
}

I stedet for at erklære @Category annotering på en testklasse, kan vi også bruge den på metodeniveau til at kategorisere individuelle testmetoder.

Ekskludering af en kategori fra testen byggefasen er enkel:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <excludedGroups>com.baeldung.maven.it.Integration</excludedGroups>
    </configuration>
</plugin>

Herunder Integration kategori i integrationstesten fase er også ligetil:

<profile>
    <id>category</id>
        <build>
        <plugins>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.0</version>
                <configuration>
                    <includes>
                        <include>**/*</include>
                    </includes>
                    <groups>com.baeldung.maven.it.Integration</groups>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Vi kan nu køre integrationstest med en Maven-kommando:

mvn verify -Pcategory

8. Tilføjelse af en separat mappe til integrationstest

Det er til tider ønskeligt at have en separat mappe til integrationstest. Ved at organisere test på denne måde kan vi fuldstændig isolere integrationstests fra enhedstests.

Vi kan bruge Maven byggehjælper plugin til dette formål:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.0.0</version>
    <executions>
        <execution>
            <id>add-integration-test-source</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>add-test-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>src/integration-test/java</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

Her kan vi finde den seneste version af dette plugin.

Den konfiguration, vi lige har set, tilføjer en testkildemappe til buildet. Lad os tilføje en klassedefinition til den nye mappe:

public class RestITCase {
    // test method shown in subsection 2.3
}

Det er tid til at køre integrationstest i denne klasse:

mvn verify -Pfailsafe

The Maven failsafe plugin vil udføre metoder i denne testklasse på grund af den konfiguration, vi indstillede i underafsnit 3.1.

Et testkildebibliotek følger ofte med et ressourcebibliotek. Vi kan tilføje en sådan mappe i en anden udførelse element til plugin-konfigurationen:

<executions>
    ...
    <execution>
        <id>add-integration-test-resource</id>
        <phase>generate-test-resources</phase>
        <goals>
            <goal>add-test-resource</goal>
        </goals>
        <configuration>
            <resources>
                <resource>
                    <directory>src/integration-test/resources</directory>
                </resource>
            </resources>
        </configuration>
    </execution>
</executions>

9. Konklusion

Denne artikel gik over at bruge Maven til at køre integrationstest med en Jetty-server med fokus på konfigurationen af ​​Maven surefire og fejlsikker plugins.

Den komplette kildekode til denne tutorial kan findes på GitHub.


Java tag