Tests d'intégration Java avec Docker : de A à Z
\n\nLes tests d'intégration sont une étape clé du développement, permettant de vérifier l'interaction des composants d'une application avec des systèmes externes : bases de données, files de messages, services REST. L'approche traditionnelle utilisant H2 ou des serveurs intégrés entraîne souvent des écarts entre l'environnement de test et celui de production. La solution — Docker. Dans cet article, nous allons voir comment configurer les tests d'intégration d'applications Java avec Docker, en utilisant la bibliothèque Testcontainers et Docker Compose. Vous apprendrez à écrire des tests qui fonctionnent avec des conteneurs réels et à les intégrer dans CI/CD.
\n\nPourquoi Docker pour les tests d'intégration ?
\nDocker permet de lancer des conteneurs isolés avec des versions précises des dépendances (PostgreSQL, Redis, Kafka) juste avant les tests et de les détruire après. Cela garantit :
\n- \n
- L'identité avec la production — vous testez avec une base de données réelle, pas avec une émulation. \n
- L'isolation — chaque exécution de test commence dans un état propre. \n
- L'exécution parallèle — plusieurs classes de test peuvent utiliser différents conteneurs. \n
- La reproductibilité — les tests fonctionnent de la même manière sur une machine locale et dans CI. \n
Configuration du projet avec Testcontainers
\nTestcontainers est une bibliothèque Java qui gère le cycle de vie des conteneurs Docker. Ajoutons la dépendance dans pom.xml (Maven) :
<dependency>\n <groupId>org.testcontainers</groupId>\n <artifactId>testcontainers</artifactId>\n <version>1.19.3</version>\n <scope>test</scope>\n</dependency>\n<dependency>\n <groupId>org.testcontainers</groupId>\n <artifactId>postgresql</artifactId>\n <version>1.19.3</version>\n <scope>test</scope>\n</dependency>\n<dependency>\n <groupId>org.springframework.boot</groupId>\n <artifactId>spring-boot-starter-test</artifactId>\n <scope>test</scope>\n</dependency>\n\nPour Gradle, ajoutez dans build.gradle :
testImplementation 'org.testcontainers:testcontainers:1.19.3'\ntestImplementation 'org.testcontainers:postgresql:1.19.3'\n\nExemple : test d'un repository avec PostgreSQL
\nConsidérons un service simple pour gérer les utilisateurs. Créons un test qui lance un conteneur PostgreSQL et vérifie la sauvegarde des données.
\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.DynamicPropertyRegistry;\nimport org.springframework.test.context.DynamicPropertySource;\nimport org.testcontainers.containers.PostgreSQLContainer;\nimport org.testcontainers.junit.jupiter.Container;\nimport org.testcontainers.junit.jupiter.Testcontainers;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n@Testcontainers\n@SpringBootTest\nclass UserRepositoryTest {\n\n @Container\n static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")\n .withDatabaseName("testdb")\n .withUsername("test")\n .withPassword("test");\n\n @DynamicPropertySource\n static void configureProperties(DynamicPropertyRegistry registry) {\n registry.add("spring.datasource.url", postgres::getJdbcUrl);\n registry.add("spring.datasource.username", postgres::getUsername);\n registry.add("spring.datasource.password", postgres::getPassword);\n }\n\n @Autowired\n private UserRepository userRepository;\n\n @Test\n void shouldSaveAndFindUser() {\n User user = new User("john_doe", "john@example