14. Integración con bases de datos

14.1 Introducción

La integración con bases de datos es una de las formas más comunes de pruebas de integración. Muchos sistemas dependen de guardar, consultar, actualizar y eliminar información correctamente.

Una prueba unitaria puede verificar una regla de negocio en memoria, pero no confirma que una consulta funcione contra el esquema real, que una entidad se guarde con sus relaciones o que una migración haya dejado la base en el estado esperado.

En este tema veremos cómo probar integraciones con bases de datos de manera clara, segura y repetible.

14.2 Qué se verifica al integrar con una base de datos

Una prueba de integración con base de datos puede verificar varias cosas:

  • Que la aplicación pueda conectarse a la base correcta.
  • Que el esquema exista y sea compatible con el código.
  • Que las consultas devuelvan los datos esperados.
  • Que las inserciones guarden todos los campos necesarios.
  • Que las actualizaciones modifiquen solo lo correspondiente.
  • Que las eliminaciones sean físicas o lógicas según la regla definida.
  • Que las relaciones entre tablas o entidades se mantengan consistentes.
Probar integración con base de datos no es probar el motor de base de datos. Es probar que nuestra aplicación lo usa correctamente.

14.3 Base real de prueba

Para este tipo de integración, conviene usar una base de datos real de prueba, separada de producción. Esto permite detectar problemas que no aparecerían si todo se simula.

Una base real de prueba permite verificar:

  • Tipos de columnas.
  • Restricciones de unicidad.
  • Claves primarias y foráneas.
  • Índices relevantes.
  • Consultas reales.
  • Transacciones.
  • Migraciones aplicadas.

La base debe ser de prueba. Nunca debería apuntarse accidentalmente a una base productiva.

14.4 Esquema y migraciones

El esquema de la base de datos define tablas, columnas, restricciones, índices y relaciones. Si el esquema no coincide con lo que espera el código, la integración fallará.

Las migraciones ayudan a versionar cambios en el esquema. En pruebas de integración, es importante verificar que la base se prepare con las migraciones correctas.

Errores típicos:

  • Falta una columna que el código intenta leer.
  • Una columna cambió de tipo.
  • Una restricción impide guardar datos que antes eran válidos.
  • Una relación obligatoria no se carga en los datos de prueba.
  • El ambiente tiene migraciones pendientes.

14.5 Repositorios y acceso a datos

Muchas aplicaciones encapsulan el acceso a datos en repositorios, DAOs o capas similares. Estas piezas son candidatas naturales para pruebas de integración porque dependen de una base real.

Una prueba puede verificar que un repositorio:

  • Guarde una entidad nueva.
  • Encuentre un registro por identificador.
  • Filtre correctamente por estado, fecha o usuario.
  • Actualice solo los campos esperados.
  • No devuelva registros eliminados lógicamente.
  • Respete ordenamientos o paginación.

Estas pruebas son útiles porque muchas fallas ocurren en la traducción entre objetos del código y registros de base de datos.

14.6 Persistencia de entidades relacionadas

Una integración con base de datos suele involucrar relaciones. Por ejemplo, una orden puede tener un cliente, varios ítems y pagos asociados.

La prueba debe verificar que:

  • Las entidades relacionadas se guarden correctamente.
  • Las claves foráneas apunten a registros existentes.
  • Las colecciones relacionadas no se pierdan.
  • Las relaciones obligatorias sean validadas.
  • La lectura posterior reconstruya la información esperada.

Probar solo la entidad principal puede ocultar errores en relaciones y datos secundarios.

14.7 Consultas y filtros

Las consultas son una fuente frecuente de errores de integración. Un filtro puede estar invertido, una condición puede faltar o un join puede excluir registros válidos.

Conviene probar consultas importantes con datos preparados específicamente para revelar errores.

Por ejemplo, para probar una consulta de pedidos pendientes, deberíamos preparar:

  • Un pedido pendiente que debe aparecer.
  • Un pedido pagado que no debe aparecer.
  • Un pedido cancelado que no debe aparecer.
  • Pedidos de otro usuario si el filtro por usuario es parte del contrato.

No alcanza con cargar un solo registro que coincide. También necesitamos datos que no deben coincidir para comprobar que el filtro excluye correctamente.

14.8 Restricciones de base de datos

Las restricciones ayudan a proteger la consistencia de los datos. En integración, es importante saber cómo responde la aplicación cuando una restricción se cumple o se viola.

Ejemplos de restricciones:

  • Campo obligatorio.
  • Valor único.
  • Clave foránea.
  • Valor dentro de un rango.
  • Longitud máxima de texto.

La prueba puede verificar que la aplicación no intente guardar datos inválidos o que maneje correctamente el error de la base cuando ocurre.

14.9 Datos iniciales para base de datos

Las pruebas con base de datos necesitan datos iniciales bien definidos. Estos datos pueden cargarse con scripts, fixtures, fábricas o pasos de preparación dentro de la prueba.

Los datos iniciales deben ser:

  • Suficientes para el escenario.
  • Coherentes con las restricciones.
  • Fáciles de entender.
  • Independientes de otras pruebas.
  • Fáciles de limpiar.

Los datos de prueba deben expresar el caso que se está verificando. Si son demasiado grandes o genéricos, la prueba pierde claridad.

14.10 Limpieza en bases de datos

Las pruebas de integración con base de datos deben limpiar los datos creados o restaurar un estado conocido. Si no, aparecen duplicados, interferencias y fallas dependientes del orden.

Estrategias posibles:

  • Transacciones revertidas al finalizar.
  • Eliminación selectiva de registros creados.
  • Truncado de tablas antes de cada suite.
  • Recreación completa de la base.
  • Uso de bases separadas por proceso de prueba.

La estrategia debe equilibrar seguridad, velocidad y simplicidad.

14.11 Transacciones

Las transacciones permiten agrupar operaciones para que se confirmen o se reviertan como una unidad. En pruebas de integración, son importantes por dos motivos: ayudan a probar consistencia y pueden ayudar a limpiar.

Una prueba puede verificar que:

  • Una operación exitosa confirme todos los cambios.
  • Una falla revierta cambios parciales.
  • No queden registros incompletos después de un error.
  • La aplicación informe adecuadamente la falla.

El tema siguiente profundizará en transacciones, persistencia y consistencia de datos.

14.12 Bases de datos en memoria

Algunas pruebas usan bases de datos en memoria porque son rápidas y fáciles de crear. Pueden ser útiles, pero tienen limitaciones.

Opción Ventaja Riesgo
Base en memoria Rápida y simple para pruebas pequeñas. Puede comportarse distinto a la base real.
Base real de prueba Detecta diferencias reales de tipos, consultas y restricciones. Requiere más preparación y limpieza.

Si producción usa un motor específico, conviene que las pruebas importantes usen el mismo motor o uno muy compatible.

14.13 Rendimiento de consultas en integración

Las pruebas de integración no reemplazan a las pruebas de rendimiento, pero pueden revelar problemas obvios en consultas. Por ejemplo, una consulta que hace muchas lecturas innecesarias o que falla con un conjunto de datos moderado.

En este nivel, conviene prestar atención a:

  • Consultas que traen más datos de los necesarios.
  • Relaciones cargadas de forma inesperada.
  • Paginación mal aplicada.
  • Filtros que no usan índices previstos.
  • Operaciones que se vuelven lentas con datos representativos.

No se trata de medir capacidad máxima, sino de detectar problemas técnicos evidentes antes de avanzar.

14.14 Ejemplo: guardar y consultar una orden

Supongamos que queremos probar la integración del servicio de órdenes con la base de datos.

Paso Qué verifica
Preparar cliente y producto. Datos iniciales suficientes para crear la orden.
Ejecutar creación de orden. El servicio colabora con el repositorio.
Consultar la orden guardada. La persistencia se realizó correctamente.
Verificar ítems y total. Las relaciones y cálculos quedaron registrados.
Limpiar datos creados. La prueba no deja residuos para otras pruebas.

14.15 Errores comunes

Al probar integración con bases de datos, suelen aparecer errores como:

  • Apuntar a la base incorrecta.
  • No aplicar migraciones antes de ejecutar la prueba.
  • Depender de datos cargados manualmente.
  • No limpiar registros creados.
  • Probar consultas con datos insuficientes.
  • Usar una base en memoria que no reproduce el comportamiento real.
  • No verificar el estado final guardado.

14.16 Lista de verificación

Antes de confiar en una prueba de integración con base de datos, conviene revisar:

  • ¿La prueba usa una base de datos de prueba?
  • ¿El esquema está actualizado con las migraciones correctas?
  • ¿Los datos iniciales son claros y suficientes?
  • ¿Se verifican tanto la respuesta como el estado persistido?
  • ¿La prueba limpia los datos que crea?
  • ¿Las consultas se prueban con datos que deben coincidir y datos que no deben coincidir?
  • ¿La prueba puede ejecutarse más de una vez sin interferencias?

14.17 Qué debes recordar de este tema

  • La integración con bases de datos verifica que la aplicación use correctamente el almacenamiento.
  • Una base real de prueba ayuda a detectar problemas de esquema, consultas y restricciones.
  • Las migraciones deben aplicarse antes de ejecutar la suite.
  • Las consultas deben probarse con datos que confirmen inclusiones y exclusiones.
  • La limpieza es fundamental para evitar pruebas inestables.
  • Las bases en memoria pueden ser útiles, pero no siempre representan el motor real.

14.18 Conclusión

Las bases de datos son una fuente central de integración en muchas aplicaciones. Probar contra una base de prueba bien preparada permite detectar errores de persistencia, consultas, relaciones, restricciones y configuración.

Una buena prueba de integración con base de datos no solo ejecuta una operación. También prepara datos, verifica el estado final y limpia lo que creó.

En el próximo tema profundizaremos en transacciones, persistencia y consistencia de datos.