Test d’intégration avec Maven

Test d'intégration avec Maven

1. Vue d'ensemble

Maven est l'outil de construction le plus populaire dans l'espace Java, tandis que les tests d'intégration constituent une partie essentielle du processus de développement. Par conséquent,it’s a natural choice to configure and execute integration tests with Maven.

Dans ce didacticiel, nous allons passer en revue différentes manières d'utiliser Maven pour les tests d'intégration et de séparer les tests d'intégration des tests unitaires.

2. Préparation

Pour rendre le code de démonstration proche d'un projet réel, nous allons configurer une application JAX-RS. Cette application est déployée sur un serveur avant l'exécution des tests d'intégration puis démantelée.

2.1. Configuration Maven

Nous allons créer notre application REST autour de Jersey, l’implémentation de référence de JAX-RS. Cette implémentation nécessite quelques dépendances:


    org.glassfish.jersey.containers
    jersey-container-servlet-core
    2.27


    org.glassfish.jersey.inject
    jersey-hk2
    2.27

Nous pouvons trouver les dernières versions de ces dépendanceshere ethere.

Nous utiliserons le plug-in Jetty Maven pour configurer un environnement de test. This plugin starts a Jetty server during the pre-integration-test phase of the Maven build lifecycle, then stops it in the post-integration-test phase.

Voici comment nous configurons le plugin Jetty Maven danspom.xml:


    org.eclipse.jetty
    jetty-maven-plugin
    9.4.11.v20180605
    
        
            8999
        
        quit
        9000
    
    
        
            start-jetty
            pre-integration-test
            
                start
            
        
        
            stop-jetty
            post-integration-test
            
                stop
            
        
    

Lorsque le serveur Jetty démarre, il écoute sur le port8999. Les éléments de configurationstopKey etstopPort sont utilisés uniquement par l'objectifstop du plugin et leur valeur n'est pas importante de notre point de vue.

Here est l'endroit où trouver la dernière version du plugin Jetty Maven.

Une autre chose à noter est que nous devons définir l'élémentpackaging du fichierpom.xml surwar, sinon le plugin Jetty ne peut pas démarrer le serveur:

war

2.2. Créer une application REST

Le point final de l'application est très simple: il renvoie un message de bienvenue lorsqu'une demande GET frappe la racine de contexte:

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

Voici comment enregistrer la classe de points de terminaison avec Jersey:

package com.example.maven.it;

import org.glassfish.jersey.server.ResourceConfig;

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

Pour que le serveur Jetty connaisse notre application REST, nous pouvons utiliser un descripteur de déploiement classique deweb.xml:


    
        rest-servlet
        org.glassfish.jersey.servlet.ServletContainer
        
            javax.ws.rs.Application
            com.example.maven.it.EndpointConfig
        
    
    
        rest-servlet
        /*
    

This descriptor must be placed in the directory /src/main/webapp/WEB-INF à reconnaître par le serveur.

2.3. Code de test côté client

Toutes les classes de test dans les sections suivantes contiennent une seule méthode:

@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 example!", responseBody);
    }
}

Comme nous pouvons le constater, cette méthode ne fait qu’envoyer une requête GET à l’application Web que nous avons précédemment configurée et en vérifiant la réponse.

3. Test d'intégration en action

Une chose importante à noter à propos des tests d'intégration est quetest methods often take quite a long time to run.

Par conséquent, nous devrions exclure les tests d'intégration du cycle de vie de génération par défaut, en évitant qu'ils ne ralentissent l'ensemble du processus à chaque fois que nous construisons un projet.

A convenient way to separate integration tests is to use build profiles. Ce type de configuration nous permet d'exécuter des tests d'intégration uniquement lorsque cela est nécessaire - en spécifiant un profil approprié.

Dans les sections suivantes, nous allons configurer tous les tests d'intégration avec des profils de build.

4. Test avec le plug-in Failsafe

La manière la plus simple d'exécuter des tests d'intégration est d'utiliserthe Maven failsafe plugin.

Par défaut, le plugin Mavensurefire exécute des tests unitaires pendant la phasetest, tandis quethe failsafe plugin runs integration tests in the integration-test phase.

Nous pouvons nommer des classes de tests avec des modèles différents pour que ces plugins récupèrent les tests inclus séparément.

Les conventions de dénomination par défaut appliquées parsurefire etfailsafe sont différentes, il suffit donc de suivre ces conventions pour séparer les tests unitaires et d'intégration.

L'exécution du pluginsurefire inclut toutes les classes dont le nom commence parTest, ou se termine parTest,Tests ouTestCase. En revanche, le pluginfailsafe exécute des méthodes de test dans les classes dont le nom commence parIT, ou se termine parIT ouITCase.

This est l'endroit où nous pouvons trouver la documentation concernant l'inclusion de test poursurefire, ethere est celle pourfailsafe.

Ajoutons le pluginfailsafe au POM avec la configuration par défaut:


    failsafe
    
        
            
                maven-failsafe-plugin
                2.22.0
                
                    
                        
                            integration-test
                            verify
                        
                    
                
            
        
    

This link est l'endroit où trouver la dernière version du pluginfailsafe.

Avec la configuration ci-dessus, la méthode de test suivante sera exécutée dans la phaseintegration-test:

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

Puisque le serveur Jetty démarre dans la phasepre-integration-test et s'arrête danspost-integration-test, le test que nous venons de voir passe avec cette commande:

mvn verify -Pfailsafe

Nous pouvons également personnaliser les modèles de dénomination pour inclure des classes avec des noms différents:


    maven-failsafe-plugin
    2.22.0
    
        
            **/*RestIT
            **/RestITCase
        
    
    ...

5. Test avec le plug-in Surefire

En dehors du pluginfailsafe,we can also use the surefire plugin to execute unit and integration tests in different phases.

Supposons que nous voulions nommer tous les tests d'intégration avec le suffixeIntegrationTest. Puisque le pluginsurefire exécute par défaut des tests avec un tel nom dans la phasetest, nous devons les exclure de l'exécution par défaut:


    maven-surefire-plugin
    2.22.0
    
        
            **/*IntegrationTest
        
    

La dernière version de ce plugin esthere.

Nous avons retiré toutes les classes de test dont le nom se termine parIntegrationTest du cycle de vie de la compilation. Il est temps de les remettre avec un profil:


    surefire
    
        
            
                maven-surefire-plugin
                2.22.0
                
                    
                        integration-test
                        
                            test
                        
                        
                            
                                none
                            
                            
                                **/*IntegrationTest
                            
                        
                    
                
            
        
    

Instead of binding the test goal of the surefire plugin to the test build phase, as usual, we bound it to the integration-test phase. Le plugin se lancera alors pendant le processus de test d'intégration.

Notez que nous devons définir un élémentexclude surnone pour remplacer l'exclusion spécifiée dans la configuration de base.

Maintenant, définissons une classe de test d'intégration avec notre modèle de dénomination:

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

Ce test sera exécuté avec la commande:

mvn verify -Psurefire

6. Tester avec le plug-in Cargo

Nous pouvons utiliser le pluginsurefire avec le plugin Mavencargo. Ce plugin est livré avec un support intégré pour les serveurs intégrés, qui sont très utiles pour les tests d'intégration.

Plus de détails sur cette combinaison peuvent être trouvéshere.

7. Test avec les@Category de JUnit

Un moyen pratique d'exécuter des tests de manière sélective consiste à tirer parti dethe @Category annotation dans le framework JUnit 4. This annotation lets us exclude particular tests from unit testing, and include them in integration testing.

Tout d'abord, nous avons besoin d'une interface ou d'une classe pour fonctionner en tant qu'identificateur de catégorie:

package com.example.maven.it;

public interface Integration { }

On peut ensuite décorer une classe de test avec l'annotation@Category et l'identifiantIntegration:

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

Plutôt que de déclarer l'annotation@Category sur une classe de test, nous pouvons également l'utiliser au niveau de la méthode pour catégoriser les méthodes de test individuelles.

Exclure une catégorie de la phase de construction detest est simple:


    maven-surefire-plugin
    2.22.0
    
        com.example.maven.it.Integration
    

L'inclusion de la catégorieIntegration dans la phaseintegration-test est également simple:


    category
        
        
            
                maven-failsafe-plugin
                2.22.0
                
                    
                        **/*
                    
                    com.example.maven.it.Integration
                
                
                    
                        
                            integration-test
                            verify
                        
                    
                
            
        
    

Nous pouvons maintenant exécuter des tests d'intégration avec une commande Maven:

mvn verify -Pcategory

8. Ajout d'un répertoire distinct pour les tests d'intégration

Il est parfois souhaitable d’avoir un répertoire distinct pour les tests d’intégration. Organizing tests this way allows us to entirely isolate integration tests from unit tests.

Nous pouvons utiliser le plugin Mavenbuild helper à cet effet:


    org.codehaus.mojo
    build-helper-maven-plugin
    3.0.0
    
        
            add-integration-test-source
            generate-test-sources
            
                add-test-source
            
            
                
                    src/integration-test/java
                
            
        
    

Here est l'endroit où nous pouvons trouver la dernière version de ce plugin.

La configuration que nous venons de voir ajoute un répertoire source de test à la construction. Ajoutons une définition de classe à ce nouveau répertoire:

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

Il est temps d’exécuter des tests d’intégration dans cette classe:

mvn verify -Pfailsafe

Le plugin Mavenfailsafe exécutera les méthodes de cette classe de test en raison de la configuration définie dans la sous-section 3.1.

Un répertoire de source de test est souvent associé à un répertoire de ressources. Nous pouvons ajouter un tel répertoire dans un autre élémentexecution de la configuration du plugin:


    ...
    
        add-integration-test-resource
        generate-test-resources
        
            add-test-resource
        
        
            
                
                    src/integration-test/resources
                
            
        
    

9. Conclusion

Cet article est passé en revue l'utilisation de Maven pour exécuter des tests d'intégration avec un serveur Jetty, en se concentrant sur la configuration des plugins Mavensurefire etfailsafe.

Le code source complet de ce didacticiel se trouve àover on GitHub.