Integrationstests von TypeScript mit Docker: Vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Integrationstests von TypeScript mit Docker: von A bis Z

\n\n

Moderne TypeScript-Entwicklung erfordert nicht nur qualitativ hochwertige Unit-Tests, sondern auch die Überprüfung der Interaktion von Komponenten unter realen Bedingungen. Integrationstests mit Docker ermöglichen es, isolierte Umgebungen mit Datenbanken, Caches und anderen Diensten zu erstellen, was die Tests so nah wie möglich an die Produktion bringt. In diesem Artikel werden wir erläutern, wie man Integrationstests für eine TypeScript-Anwendung mit Docker einrichtet, Tests für die REST-API schreibt und Best Practices betrachtet.

\n\n

Warum Docker für Integrationstests?

\n\n

Docker löst eines der Hauptprobleme von Integrationstests – die Abhängigkeit von externen Diensten. Anstatt eine gemeinsame Datenbank oder Redis zu verwenden, die von anderen Entwicklern belegt sein könnten, erstellen wir für jeden Testlauf isolierte Container. Dies garantiert:

\n\n
    \n
  • Sauberkeit der Tests: jeder Start beginnt mit einem leeren Zustand
  • \n
  • Wiederholbarkeit: Tests funktionieren auf jedem Rechner gleich
  • \n
  • Isolation: Tests beeinflussen sich weder gegenseitig noch Produktionsdaten
  • \n
  • Geschwindigkeit: Container werden in Sekunden gestartet
  • \n
\n\n

Einrichtung des Projekts und Docker Compose

\n\n

Wir erstellen ein einfaches Projekt mit TypeScript, Express und PostgreSQL. Unsere Aufgabe ist es, den Endpunkt zum Erstellen eines Benutzers zu testen. Beginnen wir mit der Datei docker-compose.test.yml:

\n\n
version: '3.8'\nservices:\n  db_test:\n    image: postgres:15-alpine\n    environment:\n      POSTGRES_DB: testdb\n      POSTGRES_USER: testuser\n      POSTGRES_PASSWORD: testpass\n    ports:\n      - "5433:5432"\n    healthcheck:\n      test: ["CMD-SHELL", "pg_isready -U testuser -d testdb"]\n      interval: 5s\n      timeout: 5s\n      retries: 5\n\n  app_test:\n    build:\n      context: .\n      dockerfile: Dockerfile.test\n    environment:\n      DATABASE_URL: postgres://testuser:testpass@db_test:5432/testdb\n      NODE_ENV: test\n    ports:\n      - "3001:3000"\n    depends_on:\n      db_test:\n        condition: service_healthy
\n\n

Jetzt erstellen wir Dockerfile.test zum Bauen der TypeScript-Anwendung:

\n\n
FROM node:18-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --only=production\nCOPY . .\nRUN npm run build\nCMD ["node", "dist/index.js"]
\n\n

Schreiben von Integrationstests mit Jest und Supertest

\n\n

Installieren wir die erforderlichen Pakete:

\n\n
npm install --save-dev jest @types/jest ts-jest supertest @types/supertest
\n\n

Erstellen wir die Jest-Konfiguration (jest.config.ts):

\n\n
export default {\n  preset: 'ts-jest',\n  testEnvironment: 'node',\n  testMatch: ['**/__tests__/**/*.test.ts'],\n  setupFilesAfterSetup: ['./jest.setup.ts'],\n  testTimeout: 30000,\n};
\n\n

Die Datei jest.setup.ts ist für das Starten und Stoppen der Docker-Container verantwortlich:

\n\n
import { execSync, spawn } from 'child_process';\nimport path from 'path';\n\nconst composeFile = path.resolve(__dirname, '../docker-compose.test.yml');\n\nbeforeAll(async () => {\n  // Container starten\n  execSync(`docker-compose -f ${composeFile} up -d --build`, { stdio: 'inherit' });\n  \n  // Warten, bis die Anwendung verfügbar ist\n  await new Promise((resolve) => setTimeout(resolve, 5000));\n});\n\nafterAll(async () => {\n  // Container stoppen und entfernen\n  execSync(`docker-compose -f ${composeFile} down -v`, { stdio: 'inherit' });\n});
\n\n

Jetzt schreiben wir den eigentlichen Test. Erstellen wir die Datei __tests__/users.test.ts:

\n\n
import request from 'supertest';\n\nconst BASE_URL = 'http://localhost:3001/api';\n\ndescribe('Users API Integration Tests', () => {\n  const testUser = {\n    name: 'Ivan Ivanov',\n    email: 'ivan@example.com',\n    password: 'securePass123'\n  };\n\n                

Blogs

Buchempfehlungen