Pruebas de integración Java con Docker: de la A a la Z
\n\nLas pruebas de integración son una etapa clave del desarrollo que permite verificar la interacción de los componentes de la aplicación con sistemas externos: bases de datos, colas de mensajes, servicios REST. El enfoque tradicional con H2 o servidores integrados a menudo genera discrepancias entre los entornos de prueba y producción. La solución es Docker. En este artículo, analizaremos cómo configurar las pruebas de integración de aplicaciones Java con Docker, utilizando la biblioteca Testcontainers y Docker Compose. Aprenderá a escribir pruebas que funcionan con contenedores reales y cómo integrarlas en CI/CD.
\n\n¿Por qué Docker para pruebas de integración?
\nDocker permite levantar contenedores aislados con versiones exactas de las dependencias (PostgreSQL, Redis, Kafka) justo antes de las pruebas y destruirlos después. Esto garantiza:
\n- \n
- Identidad con producción — prueba con una base de datos real, no con una emulación. \n
- Aislamiento — cada ejecución de prueba comienza con un estado limpio. \n
- Ejecución paralela — varias clases de prueba pueden usar diferentes contenedores. \n
- Reproducibilidad — las pruebas funcionan igual en la máquina local y en CI. \n
Configuración del proyecto con Testcontainers
\nTestcontainers es una biblioteca Java que gestiona el ciclo de vida de los contenedores Docker. Agreguemos la dependencia en 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\nPara Gradle, agregue en build.gradle:
testImplementation 'org.testcontainers:testcontainers:1.19.3'\ntestImplementation 'org.testcontainers:postgresql:1.19.3'\n\nEjemplo: prueba de repositorio con PostgreSQL
\nConsideremos un servicio simple para trabajar con usuarios. Crearemos una prueba que levanta un contenedor PostgreSQL y verifica el guardado de datos.
\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