Quarkus et Testcontainers

Quarkus et Testcontainers

Si vous ne connaissait pas Quarkus, voici un article d’introduction : Zoom sur Quarkus.

Quarkus offre un support des Tests Unitaires (TU) avec JUnit 5 via l’annotation @QuarkusTest, la documentation du support des TU de Quarkus peut être trouvé ici.

Voici un exemple de TU tiré du Quickstart Hibernate ORM :

@QuarkusTest
public class FruitsEndpointTest {

    @Test
    public void testListAllFruits() {
        given()
              .when().get("/fruits")
              .then()
              .statusCode(200)
              .body(
                    containsString("Cherry"),
                    containsString("Apple"),
                    containsString("Banana")
                    );
    }
}

Classiquement, on peut exécuter des tests en utilisant une base de données embarquée, Quarkus supporte la BDD H2 pour ça. Mais si on veut que nos tests tournent dans un environnement qui ressemble le plus à la production, l’utilisation de la même base de données est idéale.

On voudrait donc pouvoir utiliser une base de données Postgres pour exécuter nos tests.

Testcontainers est une librairie qui permet de facilement démarrer un conteneur Docker au sein de vos TUs. Il fournit une extension JUnit 5 et une extension permettant de facilement lancer des bases de données. Son utilisation serait donc idéale pour lancer une base de données Postgres pour nos TUs.

L’intégration classique de Testcontainers se fait via l’annotation @Testcontainers qui permet de démarrer l’extension JUnit 5 pour Testcontainers et permet de démarrer des conteneurs via @Container, voir la documentation de l’extension Junit 5 de Testcontainers.

Le soucis c’est que les deux extensions, celle de Quarkus et celle de Testcontainers, ne fonctionne pas très bien ensemble car Quarkus va démarrer avant Testcontainers et le conteneur ne sera pas démarré avant le démarrage de l’application Quarkus. La base de données ne sera donc pas démarré lors du démarrage de votre application et celle-ci ne réussira donc pas à démarrer.

Avec JUnit 5, on devrait pouvoir ordonner les extensions entre elles via @ExtendWith mais ce n’est pas possible d’utiliser cette annotation avec Testcontainers (plus d’info ici).

La solution ? L’utilisation d’une URL JDBC modifiée pour Testcontainers (documentée ici).

Pour notre exemple il faut tout d’abord ajouter les dépendances Testcontainers à notre pom.xml.

    <dependency>
      <groupId>org.testcontainers</groupId>
      <artifactId>testcontainers</artifactId>
      <version>${testcontainers.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.testcontainers</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>${testcontainers.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.testcontainers</groupId>
      <artifactId>postgresql</artifactId>
      <version>${testcontainers.version}</version>
      <scope>test</scope>
    </dependency>

Ensuite, ajouter l’annotation @Testcontainers à notre FruitsEndpointTest.

Pour finir configurer notre datasource via notre application.properties en utilisant une URL JDBC modifiée pour Testcontainers :

quarkus.datasource.url = jdbc:tc:postgresql:11.3://hostname/mydatabase
quarkus.datasource.driver = org.testcontainers.jdbc.ContainerDatabaseDriver
quarkus.hibernate-orm.dialect = org.hibernate.dialect.PostgreSQLDialect

Attention, il faut alors spécifier le dialect Hibernate car la sélection automatique de dialect ne fonctionne pas quand l’URL JDBC est modifiée.

Une fois tout ça configuré, lorsque Quarkus initialisera sa datasource, Testcontainers démarrera automatiquement un conteneur Postgres et vous verrez les lignes suivantes dans vos logs :

2020-02-17 15:03:20,078 INFO  [org.tes.doc.DockerClientProviderStrategy] (Agroal_5751340441) Loaded org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy from ~/.testcontainers.properties, will try it first
2020-02-17 15:03:20,283 INFO  [org.tes.doc.EnvironmentAndSystemPropertyClientProviderStrategy] (Agroal_5751340441) Found docker client settings from environment
2020-02-17 15:03:20,283 INFO  [org.tes.doc.DockerClientProviderStrategy] (Agroal_5751340441) Found Docker environment with Environment variables, system properties and defaults. Resolved dockerHost=unix:///var/run/docker.sock
2020-02-17 15:03:20,374 INFO  [org.tes.DockerClientFactory] (Agroal_5751340441) Docker host IP address is localhost
2020-02-17 15:03:20,390 INFO  [org.tes.DockerClientFactory] (Agroal_5751340441) Connected to docker: 
[...]
2020-02-17 15:03:20,958 INFO  [org.tes.DockerClientFactory] (Agroal_5751340441) Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
2020-02-17 15:03:20,970 INFO  [🐳 .3]] (Agroal_5751340441) Creating container for image: postgres:11.3
2020-02-17 15:03:21,009 INFO  [🐳 .3]] (Agroal_5751340441) Starting container with ID: c40f75e48f238f2aafe14899adae0afd3a3948396c19247aff64811166d4b057
2020-02-17 15:03:21,390 INFO  [🐳 .3]] (Agroal_5751340441) Container postgres:11.3 is starting: c40f75e48f238f2aafe14899adae0afd3a3948396c19247aff64811166d4b057
2020-02-17 15:03:23,038 INFO  [🐳 .3]] (Agroal_5751340441) Container postgres:11.3 started in PT2.067585S

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.