Tests de integración con Testcontainers y Spring Boot
17-02-2020
Para añadir más opciones a nuestra caja de herramientas a la hora de trabajar con Docker y Spring Boot, vamos a ver cómo utilizar Testcontainers a la hora de testear nuestra aplicación.
¿Testcontainers?
Testcontainers es una librería Java que facilita la creación de bases de datos "de usar y tirar" o cualquier otra cosa que se pueda ejecutar en un contenedor Docker.
Uno de los casos de uso más útiles, es tener una base de datos dockerizada sobre la que poder lanzar nuestros tests de integración.
Por suerte, utilizar Testcontainers con Spring Boot no puede ser más sencillo. Aquí tienes un ejemplo utilizando una base de datos MySQL:
Dependencias
Lo primero sería añadir las dependencias según nuestra base de datos, en este caso para MySQL sería:
Con Gradle:
testCompile "org.testcontainers:mysql:1.12.5"
Con Maven:
<dependency> <groupId>org.testcontainers</groupId> <artifactId>mysql</artifactId> <version>1.12.5</version> <scope>test</scope> </dependency>
Existen módulos para PostgreSQL, MariaDB, MSSQL...
Configuración
Ahora, debemos configurar Testcontainers e indicar a Spring que queremos trabajar con nuestra base de datos " dockerizada" en nuestros tests de integración.
Esto lo podemos conseguir dividiendo la configuración del proyecto en dos: por un lado, tendríamos la configuración principal; y, por otro, la configuración para los tests.
Con Spring Boot, esto se puede hacer creando un nuevo archivo application.yaml
con un nombre de perfil, por ejemplo:
application-local.yaml
. En este nuevo archivo configuramos nuestra base de datos dockerizada gracias a Testcontainers.
Por tanto, en nuestro archivo de configuración principal tendríamos algo como esto:
spring: datasource: url: jdbc:mysql://database:3306/my-app
Y en nuestro application-local.yaml
sobrescribimos la url así:
spring: datasource: url: jdbc:tc:mysql:8.0:///my-app?TC_INITSCRIPT=database/create_tables.sql
Como ves, la configuración se hace directamente en la url de conexión. En este caso, estamos indicando al driver de Testcontainers (tc) que queremos:
- Usar MySQL 8.0
- Una base de datos llamada
my-app
- Iniciarla con un script sql (donde tendremos los
create table
necesarios)
Y eso sería todo. A partir de esa información, Testcontainers es capaz de descargar la imagen de MySQL 8.0 e iniciarla, encargándose también de detener la ejecución de nuestro código hasta que esté todo listo. También se encarga de limpiar todo al acabar los tests.
Ejemplo de uso
El último paso sería hacer un test de integración para probar que todo funciona como esperamos. Este test lo tenemos que ejecutar con nuestro perfil "local" activado.
@ActiveProfiles("local")
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ProductHandlerTest {
private final NamedParameterJdbcTemplate jdbcTemplate;
private final WebTestClient webTestClient;
@Autowired
ProductHandlerTest(
NamedParameterJdbcTemplate jdbcTemplate,
WebTestClient webTestClient
) {
this.jdbcTemplate = jdbcTemplate;
this.webTestClient = webTestClient;
}
@Test
void returnsExistingProducts() {
executeSql(jdbcTemplate, "database/create_products.sql");
webTestClient
.get().uri("/products/1")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.name").isEqualTo("Almogrote");
}
}
Al tener el perfil local
activado, Spring carga nuestro archivo de configuración e invoca al driver de Testcontainers
que inicializa la base de datos. A partir de ahí, el jdbcTemplate
que inyectamos al test nos permite insertar datos en
nuestro MySQL dockerizado.
Conclusión

Testcontainers puede ser una herramienta útil para tener tests de integración con bases de datos reales sin tener que preocuparte de configurar Docker y demás. Con solo dos líneas de código (dependencia + url de conexión) ya lo tienes todo para empezar a trastear.
También tiene soporte para Selenium y algunas otras cosas que pueden resultar útiles.
Nota: En las pruebas he utilizado Spring Boot 2.3, en versiones anteriores es necesario indicar el driver de Testcontainers en nuestro archivo de configuración local:
driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver