Skip to main content

Probando rutas y flujos reales: pruebas de integración en el backend

Cuando la lógica de negocio ya está protegida con pruebas unitarias, el siguiente paso natural es comprobar qué ocurre cuando esa lógica se expone al mundo real.

En backend, ese “mundo real” empieza en las rutas HTTP.

Una aplicación backend no es una suma de funciones sueltas. Es un sistema donde varias capas cooperan de forma continua:

  • Rutas de Express
  • Middlewares de validación, autenticación y errores
  • Lógica de negocio
  • Persistencia en base de datos
  • Serialización de respuestas

Las pruebas de integración existen para comprobar que todas estas piezas encajan y trabajan juntas de forma correcta.

Las pruebas unitarias comprueban que cada mecánica del juego funciona por separado.

Las pruebas de integración comprueban que el nivel completo funciona cuando el jugador entra, se mueve, combate y guarda la partida.

Qué valida realmente una prueba de integración

Una prueba de integración no busca detectar errores internos muy finos. Su objetivo es otro: validar flujos reales de uso, tal y como los vive un cliente.

En una aplicación backend típica, este tipo de prueba responde a preguntas como:

  • ¿La ruta devuelve el código HTTP correcto?
  • ¿Los datos se validan antes de procesarse?
  • ¿La lógica de negocio se ejecuta en el orden esperado?
  • ¿La base de datos refleja el cambio?
  • ¿La respuesta tiene la forma que espera el cliente?

Aquí ya no se prueba “una función”, sino un contrato externo: lo que la API promete hacer.

Supertest: el puente entre tests y Express

Para ejecutar pruebas de integración sin complejidad innecesaria se utiliza Supertest.

Supertest permite simular peticiones HTTP directamente contra una aplicación Express sin levantar un servidor real ni abrir puertos.

Esto aporta ventajas muy claras:

  • Las pruebas son más rápidas
  • No hay conflictos de puertos
  • El entorno está totalmente controlado
  • El código de producción no se modifica

El test no “arranca el servidor”. Importa la aplicación Express y actúa como si fuera un cliente HTTP.

Es como probar un nivel del juego cargándolo directamente en modo depuración, sin pasar por el menú principal ni por el arranque completo.

Diferencia real entre prueba unitaria y prueba de integración

La diferencia no está en la herramienta, sino en el alcance de lo que se prueba.

Prueba unitaria

  • Ejecuta una función concreta
  • No conoce HTTP ni Express
  • No usa base de datos real
  • Falla cuando una regla interna es incorrecta

Prueba de integración

  • Ejecuta una ruta completa
  • Usa HTTP simulado
  • Pasa por middlewares y persistencia
  • Falla cuando las piezas no encajan bien

Ambos tipos de prueba son necesarios. Cada uno protege un nivel distinto del sistema.

Arquitectura mínima para integrar sin dolor

Para que las pruebas de integración sean fiables, la aplicación debe estar bien organizada.

Separación entre app y server

La aplicación Express debe exportarse sin escuchar en un puerto. El listen vive en otro archivo. Así, los tests pueden importar la app directamente.

Configuración por entorno

El entorno de testing debe activar comportamientos específicos:

  • Base de datos de prueba
  • Logs reducidos
  • Datos iniciales controlados

Esto suele hacerse con variables como NODE_ENV=test.

Base de datos aislada

Nunca se prueba contra datos reales.

Lo habitual es:

  • Usar SQLite en memoria
  • Recrear el esquema antes de cada test
  • Limpiar el estado tras cada ejecución

Sin esto, las pruebas se vuelven frágiles y peligrosas.

Flujo mental de una prueba de integración

Aunque el código cambie, el esquema conceptual siempre es el mismo.

Preparar entorno

  • App Express
  • Base de datos limpia
  • Datos iniciales (fixtures)

Ejecutar petición HTTP

  • Método (GET, POST, PUT, DELETE)
  • Ruta
  • Headers
  • Body

Verificar respuesta

  • Código HTTP
  • Estructura JSON
  • Valores concretos

Verificar efectos secundarios

  • Datos guardados
  • Estado modificado

Este flujo replica cómo interactúan realmente los clientes con el backend. Por eso las pruebas de integración son el puente entre la lógica interna y el uso real del sistema.

Ejemplo conceptual de prueba de integración

Sin entrar en sintaxis concreta, el razonamiento sería:

Pseudoflujo:

DADO un backend con base de datos vacía
Y un usuario válido existente

CUANDO envío POST /login con credenciales correctas

ENTONCES:
- recibo HTTP 200
- recibo un token
- el cuerpo tiene la estructura esperada

Aquí no importa cómo se genera el token ni qué algoritmo se usa. Importa que el contrato de la API se cumple.

Casos típicos que deben cubrirse en integración

Una buena batería de pruebas de integración suele incluir:

  • Rutas felices
    • peticiones válidas
    • datos correctos
    • respuestas exitosas
  • Errores controlados
    • datos inválidos
    • recursos inexistentes
    • permisos insuficientes
  • Estados límite
    • listas vacías
    • duplicados
    • valores fuera de rango
  • Autenticación y autorización
    • acceso con token
    • acceso sin token
    • acceso con rol incorrecto

Estos casos no suelen detectarse en pruebas unitarias, pero sí aparecen en uso real.

Pruebas de integración y regresión

Cada prueba de integración define un comportamiento que no debe romperse en el tiempo. Cuando el backend evoluciona, estas pruebas actúan como pruebas de regresión automática.

Si un cambio rompe una ruta existente:

  • La prueba falla
  • El error se detecta antes de producción
  • El contrato se protege

Este efecto es uno de los mayores valores del testing de integración.

Coste y estrategia

Las pruebas de integración son más lentas que las unitarias. Por eso no se usan para todo.

Estrategia habitual:

  • Muchas pruebas unitarias (rápidas)
  • Menos pruebas de integración (clave)
  • Cobertura sobre flujos críticos

Este equilibrio maximiza confianza sin penalizar el desarrollo diario.

Por qué este nivel es imprescindible

Sin pruebas de integración, un backend puede pasar todos los tests unitarios y aun así fallar en producción. Los errores más costosos suelen aparecer en la frontera entre capas.

Las pruebas de integración son las que confirman que:

lo que funciona bien por separado, también funciona bien en conjunto.

Cuando este nivel está bien cubierto, el backend deja de ser una caja negra frágil y se convierte en un sistema predecible, verificable y preparado para crecer.