Testing mit TypeScript
Testing mit TypeScript
~16 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026
Zum Abschluss der praktischen Werkzeuge: automatisierte Tests für unsere Bibliotheksverwaltung, mit Vitest – demselben Test-Runner, den wir bereits in "React für Profis" Kapitel 44 kennengelernt haben, hier ohne Framework-Bindung.
Vitest installieren
npm install --save-dev vitest{
"scripts": {
"start": "tsx src/index.ts",
"build": "tsc",
"typecheck": "tsc --noEmit",
"test": "vitest"
}
}Vitest versteht TypeScript NATIV, ohne zusätzliche Konfiguration – KEIN separates Kompilieren vor dem Testen nötig, GENAU wie tsx aus Kapitel 2 für die normale Ausführung.
Die Fehlerklassen aus Kapitel 25 testen
import { describe, it, expect } from 'vitest';
import { MediumNichtGefundenFehler, MediumNichtVerfuegbarFehler } from './BibliotheksFehler.js';
describe('MediumNichtGefundenFehler', () => {
it('speichert die ISBN und eine aussagekräftige Nachricht', () => {
const fehler = new MediumNichtGefundenFehler('978-3-608-93830-2');
expect(fehler.isbn).toBe('978-3-608-93830-2');
expect(fehler.message).toContain('978-3-608-93830-2');
expect(fehler).toBeInstanceOf(Error); // Vererbung aus Kapitel 25 funktioniert wie erwartet
});
});Repository<T> generisch testen
import { describe, it, expect, beforeEach } from 'vitest';
import { Repository } from './Repository.js';
import { HatIsbn } from '../models/HatIsbn.js';
interface TestElement extends HatIsbn {
name: string;
}
describe('Repository<T>', () => {
let repository: Repository<TestElement>;
beforeEach(() => {
repository = new Repository<TestElement>();
});
it('startet leer', () => {
expect(repository.anzahl()).toBe(0);
});
it('fügt Elemente hinzu', () => {
repository.hinzufuegen({ isbn: '123', name: 'Test' });
expect(repository.anzahl()).toBe(1);
});
it('findet per ISBN', () => {
repository.hinzufuegen({ isbn: '123', name: 'Test' });
const gefunden = repository.findePerIsbn('123');
expect(gefunden?.name).toBe('Test');
});
it('gibt undefined für unbekannte ISBN zurück', () => {
expect(repository.findePerIsbn('unbekannt')).toBeUndefined();
});
});TestElement extends HatIsbn definiert einen MINIMALEN Testtyp, der den Constraint aus Kapitel 18 erfüllt, statt für den Test ein volles Buch-Objekt erzeugen zu müssen – ein gängiges Testmuster: so WENIG wie möglich, so VIEL wie nötig.
Asynchronen Code testen (Kapitel 26)
import { describe, it, expect } from 'vitest';
import { AsyncBuchRepository } from './AsyncBuchRepository.js';
import { MediumNichtGefundenFehler } from '../errors/BibliotheksFehler.js';
describe('AsyncBuchRepository', () => {
it('wirft MediumNichtGefundenFehler bei unbekannter ISBN', async () => {
const repository = new AsyncBuchRepository();
await expect(repository.findeNachIsbn('unbekannt'))
.rejects.toThrow(MediumNichtGefundenFehler);
});
});it('...', async () => {{...}}) – die Test-Funktion selbst ist async, GENAU wie in Kapitel 26 gelernt. await expect(...).rejects.toThrow(...) ist Vitests spezielles Muster, um zu prüfen, dass ein PROMISE mit einem BESTIMMTEN Fehlertyp abgelehnt wird.
Bonus: Typprüfung als Teil der CI
{
"scripts": {
"start": "tsx src/index.ts",
"build": "tsc",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"verify": "npm run typecheck && npm run test"
}
}npm run verify kombiniert Kapitel 2s typecheck mit den eigentlichen Tests in EINEM Befehl – ein üblicher "vor dem Commit/Deploy"-Check, der BEIDE Fehlerklassen abdeckt: TYPFEHLER (die tsc findet) UND LOGIKFEHLER (die Tests finden). vitest run statt nur vitest beendet sich nach EINEM Durchlauf, statt im Watch-Modus zu bleiben – wichtig für CI-Umgebungen.
Tipp: Faustregel: Typprüfung UND Tests sind KOMPLEMENTÄR, nicht redundant – TypeScript fängt "falscher Typ übergeben", Tests fangen "richtiger Typ, aber falsches VERHALTEN" (z. B. eine Off-by-one-Berechnung). Beide zusammen geben deutlich mehr Sicherheit als jedes Werkzeug allein.