10. Desarrollo de tests con base de datos
El problema: MySQL en producción, ¿y en los tests?
En un sistema real suele usarse MySQL (u otro motor). Los tests no deberían depender de que alguien haya “levantado MySQL a mano” antes de pulsar Run: eso es frágil y rompe la CI.
La propuesta habitual es declarar en el propio test qué base necesitas y
crearla o conectarla al inicio de la clase de test (por ejemplo con @BeforeAll). Así el
contrato queda claro: antes de ejecutar cualquier @Test, el esquema existe y está en un estado conocido.
Opción práctica: H2 en memoria (tests rápidos)
H2 es una base embebida que puede ejecutarse en memoria. No sustituye por completo a MySQL (el SQL puede diferir), pero es ideal para probar DAOs y JDBC sin Docker.
En @BeforeAll abres la URL JDBC, ejecutas tu script .sql (o migraciones) y recién entonces
construyes el objeto que usa Connection (por ejemplo un UsuarioDAO).
Dependencias Maven (solo para test)
JUnit 5, AssertJ (assertions legibles) y H2 suelen declararse con <scope>test</scope> para no
mezclarlas con el código de producción.
Ejemplo: arranque en @BeforeAll
DB_CLOSE_DELAY=-1 evita que H2 cierre la base en memoria en cuanto se libera la última conexión (útil si
varios tests comparten la misma JVM). En un escenario real, aquí ejecutarías el DDL o cargarías un schema.sql.
Cuando necesitas MySQL de verdad
Si el SQL es muy específico de MySQL, muchos equipos usan Testcontainers: un contenedor MySQL se levanta
desde el test, obtienes la URL JDBC y ejecutas migraciones. Requiere Docker en la máquina o en CI. Otra opción es un
servicio MySQL en el pipeline (GitHub Actions services, etc.) y variables de entorno para la URL de test.
Ejercicio práctico
Escribe en comentarios al inicio de tu clase de test tres cosas: qué motor usas en test (H2/MySQL), cómo se crea el esquema (script, Flyway, etc.) y si los tests pueden ejecutarse en paralelo o deben ser secuenciales.