Integrationstests von TypeScript mit Docker: Fortgeschrittenes Niveau
\n\nIntegrationstests sind ein entscheidender Schritt zur Überprüfung der Interaktion von Systemkomponenten. Für TypeScript-Anwendungen, insbesondere bei einer Microservice-Architektur, wird Docker zu einem unverzichtbaren Werkzeug. In diesem Artikel betrachten wir fortgeschrittene Techniken zur Konfiguration und Durchführung von Integrationstests mit Docker, die Ihnen helfen, die Zuverlässigkeit und Geschwindigkeit der Entwicklung zu steigern.
\n\n1. Warum Docker für Integrationstests von TypeScript?
\nDocker ermöglicht es, Testumgebungen zu isolieren und deren Reproduzierbarkeit zu gewährleisten. Anstatt Datenbanken, Message Queues und andere Abhängigkeiten manuell zu konfigurieren, starten Sie diese in Containern. Dies ist besonders wichtig für TypeScript-Projekte, bei denen die Typisierung Laufzeitfehler verbergen kann, die erst bei der Integration auftreten.
\n- \n
- Isolation: Jeder Test wird in einer sauberen Umgebung ausgeführt \n
- Geschwindigkeit: Container starten in Sekunden \n
- Parallelität: Verschiedene Versionen von Abhängigkeiten können gleichzeitig getestet werden \n
2. Konfiguration von Docker Compose für die Testumgebung
\nWir erstellen eine docker-compose.test.yml, die PostgreSQL, Redis und die Anwendung selbst für Tests hochfährt:
version: '3.8'\nservices:\n db-test:\n image: postgres:15-alpine\n environment:\n POSTGRES_DB: testdb\n POSTGRES_USER: test\n POSTGRES_PASSWORD: testpass\n ports:\n - "5433:5432"\n tmpfs: /var/lib/postgresql/data\n\n redis-test:\n image: redis:7-alpine\n ports:\n - "6380:6379"\n\n app-test:\n build:\n context: .\n dockerfile: Dockerfile.test\n environment:\n DATABASE_URL: postgres://test:testpass@db-test:5432/testdb\n REDIS_URL: redis://redis-test:6379\n depends_on:\n - db-test\n - redis-test\n command: ["npm", "run", "test:integration"]\nHier verwenden wir tmpfs für die Datenbank, damit Daten zwischen den Läufen nicht gespeichert werden, was die Tests beschleunigt.
3. Fortgeschrittene Konfiguration von TypeScript-Tests mit TestContainers
\nDie Bibliothek testcontainers ermöglicht die Verwaltung von Containern direkt aus dem TypeScript-Code. Dies bietet Flexibilität: Sie können Container nur für bestimmte Testszenarien hochfahren.
Installation:
\nnpm install --save-dev testcontainers\nBeispiel für einen Integrationstest mit einem dynamischen Container:
\nimport { GenericContainer, StartedTestContainer } from 'testcontainers';\nimport { Client } from 'pg';\nimport { UserService } from './user-service';\n\nlet container: StartedTestContainer;\nlet client: Client;\n\nbeforeAll(async () => {\n // PostgreSQL-Container starten\n container = await new GenericContainer('postgres:15-alpine')\n .withEnvironment({\n POSTGRES_DB: 'test',\n POSTGRES_USER: 'test',\n POSTGRES_PASSWORD: 'test'\n })\n .withExposedPorts(5432)\n .start();\n\n // Mit der Testdatenbank verbinden\n const host = container.getHost();\n const port = container.getMappedPort(5432);\n client = new Client({\n host,\n port,\n database: 'test',\n user: 'test',\n password: 'test'\n });\n await client.connect();\n\n // Migrationen durchführen\n await client.query(`\n CREATE TABLE users (\n id SERIAL PRIMARY KEY,\n email VARCHAR(255) UNIQUE NOT NULL,\n name VARCHAR(255)\n )\n `);\n});\n\nafterAll(async () => {\n await client.end();\n await container.stop();\n});\n\ntest('UserService.createUser erstellt einen Benutzer in der DB', async () => {\n const userService = new UserService(client);\n const user = await userService.createUser({\n email: 'test@example.com',\n name: 'Test User'\n });\n\n const result = await client.query('SELECT * FROM users WHERE email = $1', ['test@example.com']);\n expect(result.rows[0]).toMatchObject({\n email: 'test@example.com',\n