Introduction aux tests avec Arquillian

Introduction aux tests avec Arquillian

1. Vue d'ensemble

Arquillian est un cadre de test d'intégration indépendant du conteneur pour Java EE. L'utilisation d'Arquillian minimise la charge de gestion des conteneurs, des déploiements, des initialisations d'infrastructure, etc.

Nous pouvons nous concentrer sur l'écriture de tests réels et non sur l'amorçage de l'environnement de test.

2. Concepts de base

2.1. Archives de déploiement

Il existe un moyen simple de tester notre application lors de l'exécution à l'intérieur d'un conteneur.

Premièrement, la classeShrinkWrap fournit une API pour créer des fichiers*.jar,*.war, et*.ear déployables.

Ensuite, Arquillian nous permet de configurer le déploiement de test en utilisant l'annotation@Deployment - sur une méthode qui retourne un objetShrinkWrap.

2.2. Les conteneurs

Arquillian distingue trois types de conteneurs:

  • Testé à distance à l'aide d'un protocole distant tel que JMX

  • Géré - conteneurs distants mais leur cycle de vie est géré par Arquillian

  • Embarqué - Conteneurs locaux où les tests sont effectués à l'aide de protocoles locaux

Nous pouvons également classer les conteneurs en fonction de leurs capacités:

  • Applications Java EE déployées sur un serveur d'applications tel que Glassfish ou JBoss

  • Conteneurs de servlets déployés sur Tomcat ou Jetty

  • Conteneurs autonomes

  • Conteneurs OSGI

Il examine le chemin de classe d'exécution et sélectionne automatiquement le conteneur disponible.

2.3. Enrichissement de test

Arquillian enrichit les tests en fournissant par exemple l'injection de dépendance afin que nous puissions écrire nos tests facilement.

Nous pouvons injecter des dépendances en utilisant@Inject, injecter des ressources avec@Resource, des beans session EJB en utilisant@EJB, etc.

2.4. Plusieurs testeurs

Nous pouvons créer plusieurs déploiements en utilisant l'annotation:

@Deployment(name="myname" order = 1)

Où le nom est le nom du fichier de déploiement et le paramètre order est l'ordre d'exécution du déploiement, nous pouvons donc maintenant exécuter des tests sur plusieurs déploiements en même temps en utilisant l'annotation:

@Test @OperateOnDeployment("myname")

Le test avant est exécuté sur le conteneur de déploiementmyname en utilisant l'ordre défini dans l'annotation@Deployment.

2.5. Extensions Arquillian

Arquillian propose plusieurs extensions au cas où nos besoins de test ne seraient pas couverts par l'environnement d'exécution principal. Nous avons la persistance, les transactions, client / serveur, les extensions REST, etc.

Nous pouvons activer ces extensions en ajoutant des dépendances appropriées aux fichiers de configuration Maven ou Gradle.

Les extensions couramment utilisées sont Drone, Graphene et Selenium.

3. Dépendances et configuration de Maven

Ajoutons la dépendance suivante à notre fichierpom.xml:


    org.jboss.arquillian
    arquillian-bom
    1.1.13.Final
    import
    pom


    org.glassfish.main.extras
    glassfish-embedded-all
    4.1.2
    test


    org.jboss.arquillian.container
    arquillian-glassfish-embedded-3.1
    1.0.0.Final
    test

La dernière version des dépendances peut être trouvée ici:arquillian-bom,org.glassfish.main.extras,org.jboss.arquillian.container.

4. Test simple

4.1. Créer un composant

Commençons par un composant simple. Nous n'incluons aucune logique avancée pour pouvoir se concentrer sur les tests:

public class Component {
    public void sendMessage(PrintStream to, String msg) {
        to.println(message(msg));
    }

    public String message(String msg) {
        return "Message, " + msg;
    }
}

En utilisant Arquillian, nous voulons vérifier que cette classe se comporte correctement lorsqu'elle est appelée en tant que bean CDI.

4.2. Écrivez notre premier test Arquillian

Tout d'abord, nous devons spécifier que notre classe de test doit être exécutée à l'aide du programme d'exécution spécifique à l'infrastructure:

@RunWith(Arquillian.class)

Si nous allons exécuter nos tests dans un conteneur, nous devons utiliser l'annotation@Deployment.

Arquillian n'utilise pas l'intégralité du chemin d'accès aux classes pour isoler l'archive de test. Au lieu de cela, il utilise la classeShrinkWrap, qui est une API Java pour créer des archives. Lorsque nous créons l'archive à tester, nous spécifions les fichiers à inclure dans le chemin d'accès aux classes pour utiliser le test. Pendant le déploiement,ShrinkWrap isole uniquement les classes nécessaires au test.

En utilisant la méthodeaddclass(), nous pouvons spécifier toutes les classes nécessaires, et également ajouter une ressource manifeste vide.

LeJavaArchive.class crée une maquette d'archive Web appeléetest.war, ce fichier est déployé dans le conteneur puis est utilisé par Arquillian pour effectuer des tests:

@Deployment
public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addClass(Component.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}

Ensuite, nous injectons notre composant dans le test:

@Inject
private Component component;

Enfin, nous effectuons notre test:

assertEquals("Message, MESSAGE",component.message(("MESSAGE")));

component.sendMessage(System.out, "MESSAGE");

5. Test des beans Java d'entreprise

5.1. Enterprise Java Bean

Avec Arquillian, nous pouvons tester l'injection de dépendance d'un bean Enterprise Java. Pour ce faire, nous créons une classe dotée d'une méthode permettant de convertir n'importe quel mot en minuscule:

public class ConvertToLowerCase {
    public String convert(String word){
        return word.toLowerCase();
    }
}

En utilisant cette classe, nous créons une classe sans état pour appeler la méthode créée avant:

@Stateless
public class CapsConvertor {
    public ConvertToLowerCase getLowerCase(){
        return new ConvertToLowerCase();
    }
}

La classeCapsConvertor est injectée dans un bean service:

@Stateless
public class CapsService {

    @Inject
    private CapsConvertor capsConvertor;

    public String getConvertedCaps(final String word){
        return capsConvertor.getLowerCase().convert(word);
    }
}

5.2. Tester le bean Java d'entreprise

Nous pouvons maintenant utiliser Arquillian pour tester notre Java Bean d'entreprise, en injectant lesCapsService:

@Inject
private CapsService capsService;

@Test
public void givenWord_WhenUppercase_ThenLowercase(){
    assertTrue("capitalize".equals(capsService.getConvertedCaps("CAPITALIZE")));
    assertEquals("capitalize", capsService.getConvertedCaps("CAPITALIZE"));
}

En utilisantShrinkWrap,, nous nous assurons que toutes les classes sont correctement câblées:

@Deployment
public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addClasses(CapsService.class, CapsConvertor.class, ConvertToLowerCase.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}

6. Tester JPA

6.1. Persistance

Nous pouvons également utiliser Arquillian pour tester la persistance. Tout d'abord, nous allons créer notre entité:

@Entity
public class Car {

    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    private String name;

    // getters and setters
}

Nous avons une table qui contient les noms des voitures.

Ensuite, nous allons créer notre EJB pour effectuer des opérations de base sur nos données:

@Stateless
public class CarEJB {

    @PersistenceContext(unitName = "defaultPersistenceUnit")
    private EntityManager em;

    public Car saveCar(Car car) {
        em.persist(car);
        return car;
    }

    public List findAllCars() {
    Query query
      = em.createQuery("SELECT b FROM Car b ORDER BY b.name ASC");
    List entries = query.getResultList();

    return entries == null ? new ArrayList<>() : entries;

    public void deleteCar(Car car) {
        car = em.merge(car);
        em.remove(car);
    }
}

AvecsaveCar, nous pouvons enregistrer les noms de voitures dans la base de données, nous pouvons obtenir toutes les voitures stockées avecfindAllCars, et nous pouvons également supprimer une voiture de la base de données avecdeleteCar.

6.2. Tester la persistance avec Arquillian

Nous pouvons maintenant effectuer des tests de base avec Arquillian.

Tout d'abord, nous ajoutons nos classes à nosShrinkWrap:

.addClasses(Car.class, CarEJB.class)
.addAsResource("META-INF/persistence.xml")

Ensuite, nous créons notre test:

@Test
public void testCars() {
    assertTrue(carEJB.findAllCars().isEmpty());
    Car c1 = new Car();
    c1.setName("Impala");
    Car c2 = new Car();
    c2.setName("Lincoln");
    carEJB.saveCar(c1);
    carEJB.saveCar(c2);

    assertEquals(2, carEJB.findAllCars().size());

    carEJB.deleteCar(c1);

    assertEquals(1, carEJB.findAllCars().size());
}

Dans ce test, nous créons d’abord quatre instances de voiture et nous vérifions que le nombre de lignes de la base de données est identique à celui que nous avons créé.

8. Conclusion

Dans ce tutoriel, nous:

  • introduction des concepts de base arquilliens

  • injecté un composant dans le test d'Arquillian

  • testé un EJB

  • persistance testée

  • effectué le test Arquillian avec Maven

Vous pouvez trouver le code de l'articleover on Github.