Pruebas de integración de TypeScript con Docker: nivel avanzado
Las pruebas de integración son una etapa clave en el desarrollo de aplicaciones TypeScript modernas. Cuando su sistema consta de múltiples microservicios, bases de datos, colas de mensajes y API externas, las pruebas unitarias aisladas ya no cubren los escenarios de interacción reales. Docker permite crear entornos de prueba reproducibles y aislados, cercanos a producción. En este artículo, exploraremos técnicas avanzadas de pruebas de integración para aplicaciones TypeScript usando Docker: desde la configuración de contenedores hasta la construcción de pipelines CI/CD.
Por qué Docker es la herramienta ideal para pruebas de integración de TypeScript
Los enfoques tradicionales para las pruebas de integración a menudo sufren problemas de entorno: "en mi máquina funciona". Docker resuelve este problema al proporcionar:
- Aislamiento — cada prueba se ejecuta en un contenedor limpio, sin afectar otros procesos
- Reproducibilidad — el mismo entorno en todas las etapas: local, CI, staging
- Velocidad — los contenedores ligeros se inician en segundos
- Flexibilidad — fácil combinar diferentes versiones de BD, cachés, colas
Para proyectos TypeScript, Docker es especialmente útil, ya que permite probar no solo el runtime de Node.js, sino también la interacción con el compilador TypeScript, la transpilación y la compilación.
Configuración del entorno Docker para pruebas de TypeScript
Comencemos con la configuración básica. Crearemos un Dockerfile para la compilación de producción y otro separado para las pruebas:
# Dockerfile.testFROM node:18-alpine AS builder
WORKDIR /appCOPY package*.json ./RUN npm ciCOPY tsconfig.json ./COPY src/ ./src/
# Compilación de TypeScriptRUN npm run build
# Etapa para pruebasFROM node:18-alpine AS test-runnerWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesCOPY --from=builder /app/package.json ./COPY tests/ ./tests/COPY jest.config.ts ./
# Ejecución de pruebas de integraciónCMD ["npx", "jest", "--config", "jest.config.ts", "--testMatch", "**/*.integration.test.ts"]Para gestionar múltiples servicios, usamos docker-compose.yml:
version: '3.8'services: app: build: context: . dockerfile: Dockerfile.test depends_on: postgres: condition: service_healthy redis: condition: service_healthy environment: - DB_HOST=postgres - DB_PORT=5432 - REDIS_HOST=redis - REDIS_PORT=6379 volumes: - ./tests:/app/tests:ro networks: - test-network
postgres: image: postgres:15-alpine environment: POSTGRES_DB: testdb POSTGRES_USER: testuser POSTGRES_PASSWORD: testpass healthcheck: test: ["CMD-SHELL", "pg_isready -U testuser -d testdb"] interval: 5s timeout: 5s retries: 5 networks: - test-network
redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 networks: - test-network
networks: test-network: driver: bridgeEscribiendo pruebas de integración avanzadas en TypeScript
Ahora crearemos una prueba que verifica un escenario completo: escritura en BD, almacenamiento en caché en Redis y envío de un evento a una cola. Usaremos la biblioteca testcontainers para la gestión dinámica de contenedores desde código TypeScript:
// tests/integration/user-registration.integration.test.tsimport { GenericContainer, StartedTestContainer, Wait } from 'testcontainers';import { PostgreSqlContainer } from '@testcontainers/postgresql';import { RedisContainer } from '@testcontainers/redis';import axi