Testen in TypeScript: Unit, Integration, E2E — 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

Einleitung: Warum TypeScript-Code testen?

TypeScript ist ein leistungsstarkes Werkzeug, das JavaScript um statische Typisierung erweitert und es Ihnen ermöglicht, Fehler bereits während der Kompilierung zu erkennen. Allerdings garantiert selbst das strengste Typsystem nicht, dass Ihr Code unter realen Bedingungen korrekt funktioniert. Logische Fehler, falsche Behandlung von Grenzfällen sowie Probleme bei der Integration von Modulen liegen außerhalb des Zuständigkeitsbereichs des Compilers. Hier kommt das Testen zur Rettung.

Testen in TypeScript bedeutet nicht nur, Funktionen zu überprüfen. Es ist ein umfassender Prozess, der drei Schlüsselebenen umfasst: Unit, Integration und E2E. Jede Ebene löst ihre eigene Aufgabe, und gemeinsam bilden sie die "Testpyramide", die die Zuverlässigkeit der Anwendung gewährleistet.

In diesem Artikel erläutern wir, wie Sie Tests für TypeScript auf allen drei Ebenen mit modernen Werkzeugen schreiben: Jest, Supertest und Playwright. Sie erfahren, welche Fehler diese Tests verhindern helfen und wie Sie sie in Ihrem Projekt implementieren.



Unit-Tests: Überprüfung isolierter Module

Unit-Tests sind die Basis der Pyramide. Sie testen einzelne Funktionen, Klassen oder Methoden isoliert von externen Abhängigkeiten (Datenbanken, APIs, Dateisysteme). Das Hauptziel ist sicherzustellen, dass jeder "Baustein" Ihrer Anwendung korrekt funktioniert.



Werkzeuge und Einrichtung

Das beliebteste Framework für Unit-Tests in TypeScript ist Jest. Es bietet integrierte TypeScript-Unterstützung über ts-jest oder @swc/jest.

Installation von Jest in einem Projekt:

npm install --save-dev jest @types/jest ts-jestnpx ts-jest config:init


Beispiel für einen Unit-Test

Betrachten wir eine einfache Funktion zur Berechnung eines Rabatts:

// discount.tsexport function applyDiscount(price: number, discountPercent: number): number {  if (discountPercent < 0 || discountPercent > 100) {    throw new Error('Discount percentage must be between 0 and 100');  }  return price - (price * discountPercent) / 100;}

Schreiben wir Unit-Tests, die die wichtigsten Szenarien abdecken:

// discount.test.tsimport { applyDiscount } from './discount';

describe('applyDiscount', () => { it('should correctly apply a 20% discount', () => { expect(applyDiscount(100, 20)).toBe(80); });

it('should return the original price with a 0% discount', () => { expect(applyDiscount(50, 0)).toBe(50); });

it('should return 0 with a 100% discount', () => { expect(applyDiscount(200, 100)).toBe(0); });

it('should throw an error with a negative discount', () => { expect(() => applyDiscount(100, -10)).toThrow('Discount percentage must be between 0 and 100'); });

it('should throw an error with a discount greater than 100%', () => { expect(() => applyDiscount(100, 150)).toThrow('Discount percentage must be between 0 and 100'); });});

Wichtig: Unit-Tests sollten nicht auf externe Ressourcen zugreifen. Verwenden Sie stattdessen Mocks, um Abhängigkeiten zu ersetzen, zum Beispiel mit jest.mock().



Integrationstests: Interaktion zwischen Modulen

Integrationstests überprüfen, wie verschiedene Teile des Systems zusammenarbeiten. Dies kann die Interaktion zwischen einem Dienst und einer Datenbank, einem Controller und einem Repository oder zwischen Microservices sein. Im Gegensatz zu Unit-Tests isolieren wir die Komponenten hier nicht vollständig.



Beispiel: Testen einer REST-API

Angenommen, wir haben eine Express-Anwendung mit einem Endpunkt. Zum Testen von HTTP-Anfragen verwenden wir Supertest.

// userController.tsimport { Router, Request, Response } from 'express';

interface User { id: number; name: string;}

const users: User[] = [{ id: 1, name: 'Alice' }];

Blogs

Buchempfehlungen