Pruebas de Integración de JavaScript con Docker: de la teoría a la práctica avanzada
\n\nLas pruebas de integración son una etapa crítica en el desarrollo, que verifica la interacción entre diferentes módulos y servicios externos. Para aplicaciones JavaScript en Node.js, Docker se convierte en una herramienta indispensable, permitiendo crear entornos aislados y reproducibles para las pruebas. En este artículo, exploraremos técnicas avanzadas para configurar pruebas de integración con Docker, incluyendo el trabajo con bases de datos, colas y la optimización para CI/CD.
\n\n¿Por qué Docker para pruebas de integración?
\n\nLos enfoques tradicionales para las pruebas de integración (mocks, stubs) no siempre reflejan el comportamiento real del sistema. Docker resuelve este problema proporcionando:
\n\n- \n
- Aislamiento: cada prueba se ejecuta en un contenedor limpio sin afectar a otras pruebas ni al entorno local. \n
- Reproducibilidad: las mismas condiciones de ejecución en la máquina del desarrollador y en CI/CD. \n
- Escalabilidad: posibilidad de ejecutar pruebas en paralelo con diferentes versiones de dependencias (PostgreSQL, Redis, Elasticsearch). \n
- Recuperación rápida: la recreación de contenedores toma segundos, no horas de configuración. \n
Configuración de un entorno de pruebas avanzado
\n\nConsideremos una aplicación Node.js típica que utiliza PostgreSQL y Redis. En lugar de un simple docker-compose.yml, crearemos una configuración flexible con soporte para pruebas paralelas y health checks.
Paso 1: Docker Compose con puertos dinámicos
\n\nPara evitar conflictos de puertos durante la ejecución en paralelo, utilizamos asignación dinámica:
\n\n# docker-compose.test.yml\nversion: '3.8'\nservices:\n postgres_test:\n image: postgres:15-alpine\n environment:\n POSTGRES_DB: test_db\n POSTGRES_USER: test_user\n POSTGRES_PASSWORD: test_pass\n ports:\n - "0:5432" # Puerto dinámico\n healthcheck:\n test: ["CMD-SHELL", "pg_isready -U test_user -d test_db"]\n interval: 2s\n timeout: 5s\n retries: 10\n tmpfs: /var/lib/postgresql/data # Datos en RAM para velocidad\n\n redis_test:\n image: redis:7-alpine\n ports:\n - "0:6379"\n healthcheck:\n test: ["CMD", "redis-cli", "ping"]\n interval: 2s\n timeout: 5s\n retries: 10\n\nPaso 2: Utilidades para ejecutar pruebas con Docker
\n\nCrearemos una clase auxiliar que encuentra automáticamente los puertos dinámicos y espera a que los servicios estén listos:
\n\n// test/setup/docker-manager.js\nconst { DockerComposeEnvironment, Wait } = require('testcontainers');\nconst { Client } = require('pg');\nconst Redis = require('ioredis');\n\nclass DockerTestManager {\n constructor() {\n this.environment = null;\n this.config = {\n pgPort: null,\n redisPort: null\n };\n }\n\n async start() {\n this.environment = await new DockerComposeEnvironment(\n '.', \n 'docker-compose.test.yml'\n ).withWaitStrategy('postgres_test', Wait.forHealthCheck())\n .withWaitStrategy('redis_test', Wait.forHealthCheck())\n .up();\n\n // Extraemos el mapeo de puertos\n const pgContainer = this.environment.getContainer('postgres_test');\n const redisContainer = this.environment.getContainer('redis_test');\n \n this.config.pgPort = pgContainer.getMappedPort(5432);\n this.config.redisPort = redisContainer.getMappedPort(6379);\n \n return this.config;\n }\n\n async stop() {\n if (this.environment) {\n await this.environment.down();\n }\n }\n}\n\nmodule.exports = DockerTestManager;\n\nEscenarios avanzados de pruebas de integración
\n\nAhora pasemos a pruebas específicas que verifican la interacción real de los componentes.
\n