Unit- vs. Integrationstests in JavaScript: Wann welche Teststrategie einsetzen?
Jeder JavaScript-Entwickler steht vor derselben Frage beim Aufbau zuverlässiger Anwendungen: Sollte man mehr Unit-Tests oder Integrationstests schreiben? Wählt man falsch, verschwendet man entweder Stunden mit dem Debugging fragiler Tests oder liefert Bugs in die Produktivumgebung aus. Die Antwort liegt nicht darin, sich für eine der beiden Optionen zu entscheiden – es geht darum zu verstehen, wann welcher Testtyp den größten Mehrwert liefert.
Dieser Artikel verdeutlicht die Unterschiede zwischen Unit- und Integrationstests in JavaScript, zeigt praktische Beispiele für beide Ansätze und bietet einen Entscheidungsrahmen für die ausgewogene Balance beider Strategien in Ihrer Teststrategie.
Wichtigste Erkenntnisse
- Unit-Tests verifizieren isolierte Codeabschnitte für Geschwindigkeit und Präzision
- Integrationstests validieren Komponenteninteraktionen für realitätsnahe Sicherheit
- Eine 70-20-10-Verteilung (Unit-Integration-E2E) funktioniert für die meisten JavaScript-Projekte
- Die Wahl hängt davon ab, was getestet wird: Algorithmen benötigen Unit-Tests, Workflows benötigen Integrationstests
Was sind Unit-Tests?
Unit-Tests verifizieren, dass einzelne Codeabschnitte isoliert korrekt funktionieren. Man kann es sich wie das Testen eines einzelnen LEGO-Steins vorstellen, bevor man ihn zur Konstruktion hinzufügt.
In JavaScript konzentriert sich ein Unit-Test typischerweise auf:
- Eine einzelne Funktion oder Methode
- Eine Komponente ohne ihre Kindkomponenten
- Eine bestimmte Klasse oder ein Modul
Unit-Test-Beispiel
// calculator.js
export function calculateDiscount(price, percentage) {
if (percentage < 0 || percentage > 100) {
throw new Error('Invalid percentage');
}
return price * (1 - percentage / 100);
}
// calculator.test.js
import { calculateDiscount } from './calculator';
test('applies 20% discount correctly', () => {
expect(calculateDiscount(100, 20)).toBe(80);
});
test('throws error for invalid percentage', () => {
expect(() => calculateDiscount(100, 150)).toThrow('Invalid percentage');
});
Unit-Tests glänzen durch:
- Geschwindigkeit: Millisekunden pro Test, da keine I/O-Operationen oder externe Abhängigkeiten vorhanden sind
- Präzision: Lokalisiert exakte Fehlerstellen
- Stabilität: Brechen selten aufgrund nicht zusammenhängender Änderungen
Was sind Integrationstests?
Integrationstests verifizieren, dass mehrere Teile Ihrer Anwendung korrekt zusammenarbeiten. Anstatt den LEGO-Stein allein zu testen, testet man, wie mehrere Steine miteinander verbunden werden.
Integrationstests in JavaScript decken typischerweise ab:
- Komponenteninteraktionen mit APIs
- Mehrere Module, die zusammenarbeiten
- Datenbankoperationen mit Geschäftslogik
- UI-Komponenten mit State Management
Integrationstest-Beispiel
// userProfile.test.js
import { render, screen, waitFor } from '@testing-library/react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import UserProfile from './UserProfile';
const server = setupServer(
rest.get('/api/user/:id', (req, res, ctx) => {
return res(ctx.json({
id: req.params.id,
name: 'Jane Doe',
role: 'Developer'
}));
})
);
beforeAll(() => server.listen());
afterAll(() => server.close());
test('displays user data after loading', async () => {
render(<UserProfile userId="123" />);
expect(screen.getByText(/loading/i)).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('Jane Doe')).toBeInTheDocument();
expect(screen.getByText('Developer')).toBeInTheDocument();
});
});
Integrationstests bieten:
- Vertrauen: Validiert reale Benutzer-Workflows
- Abdeckung: Testet Interaktionen zwischen Komponenten
- Realitätsnähe: Fängt Probleme auf, die Unit-Tests übersehen
Discover how at OpenReplay.com.
Wesentliche Unterschiede, die zählen
Umfang und Isolation
Unit-Tests isolieren Code mithilfe von Mocks und Stubs. Man kontrolliert jede Variable. Integrationstests verwenden wo möglich echte Implementierungen und mocken nur externe Grenzen wie APIs oder Datenbanken.
Ausführungsgeschwindigkeit
Unit-Tests laufen in 1-50ms pro Test. Man kann Tausende in Sekunden ausführen. Integrationstests benötigen 100-500ms oder mehr. Sie beinhalten Setup, Teardown und manchmal echte I/O-Operationen.
Wartungsaufwand
Unit-Tests brechen nur, wenn sich ihre spezifische Unit ändert. Integrationstests können durch Änderungen überall im getesteten Ablauf brechen und erfordern mehr Untersuchungszeit.
Fehlererkennung
Unit-Tests fangen Logikfehler und Grenzfälle in isoliertem Code ab. Integrationstests fangen Verkabelungsprobleme, falsche Annahmen und Vertragsverletzungen zwischen Komponenten ab.
Wann welchen Testtyp verwenden
Unit-Tests schreiben für:
- Pure Functions: Geschäftslogik, Berechnungen, Datentransformationen
- Komplexe Algorithmen: Sortierung, Suche, Validierungsregeln
- Grenzfälle: Fehlerbehandlung, Randbedingungen
- Hilfsfunktionen: Formatierer, Parser, Helper
Integrationstests schreiben für:
- API-Interaktionen: HTTP-Requests, Response-Handling
- Benutzer-Workflows: Mehrstufige Prozesse, Formularübermittlungen
- Komponentenintegration: Eltern-Kind-Komponentenkommunikation
- State Management: Redux Actions, Context API Flows
- Datenbankoperationen: CRUD-Operationen mit Geschäftslogik
Die praktische Teststrategie
Die meisten erfolgreichen JavaScript-Projekte folgen einer 70-20-10-Verteilung:
- 70% Unit-Tests: Schnelles Feedback, einfaches Debugging
- 20% Integrationstests: Vertrauen in Komponenteninteraktionen
- 10% End-to-End-Tests: Finale Validierung kritischer Pfade
Dies ist keine starre Regel – passen Sie sie basierend auf Ihrem Anwendungstyp an. API-lastige Anwendungen benötigen mehr Integrationstests. Algorithmus-lastige Bibliotheken benötigen mehr Unit-Tests.
Integration in die CI/CD-Pipeline
Strukturieren Sie Ihre Pipeline für schnelles Feedback:
- Pre-commit: Unit-Tests ausführen (< 5 Sekunden)
- Pull Request: Alle Unit- und Integrationstests ausführen
- Pre-deploy: Vollständige Test-Suite inklusive E2E-Tests ausführen
Tools wie Jest für Unit-Tests, Testing Library für Integrationstests und MSW für API-Mocking machen diese Pipeline effizient und wartbar.
Häufige Fallstricke vermeiden
- Übermäßiges Mocking in Integrationstests: Konterkariert den Zweck des Testens von Interaktionen
- Testen von Implementierungsdetails: Fokus auf Verhalten, nicht auf interne Struktur
- Ignorieren der Testgeschwindigkeit: Langsame Tests entmutigen häufiges Ausführen
- Tests erst nach Bugs schreiben: Proaktives Testen verhindert Probleme
Fazit
Unit- und Integrationstests in JavaScript sind keine konkurrierenden Strategien – sie sind komplementäre Werkzeuge. Unit-Tests bieten Geschwindigkeit und Präzision für isolierte Logik. Integrationstests geben Vertrauen, dass Komponenten korrekt zusammenarbeiten.
Beginnen Sie mit Unit-Tests für Geschäftslogik und Pure Functions. Fügen Sie Integrationstests für kritische Benutzerpfade und Komponenteninteraktionen hinzu. Überspringen Sie religiöse Debatten über Testphilosophien und konzentrieren Sie sich darauf, was Ihnen Vertrauen gibt, Code auszuliefern.
Die beste JavaScript-Teststrategie ist diejenige, die Bugs abfängt, bevor Benutzer sie entdecken, während sie gleichzeitig Ihre Entwicklungsgeschwindigkeit hochhält. Balancieren Sie beide Typen basierend auf den Anforderungen Ihrer Anwendung und passen Sie an, während Sie lernen, was am häufigsten bricht.
Häufig gestellte Fragen
Mocken Sie immer externe Abhängigkeiten in Unit-Tests. Dazu gehören Datenbanken, APIs, Dateisysteme und andere Services. Mocking stellt sicher, dass Tests schnell laufen, vorhersagbar bleiben und wirklich Ihren Code isoliert testen, anstatt das Verhalten externer Systeme.
Beginnen Sie mit der Frage, was kaputtgehen könnte. Wenn die Logik selbst komplex ist, schreiben Sie zuerst Unit-Tests. Wenn das Feature mehrere Komponenten umfasst, die miteinander oder mit externen Services kommunizieren, priorisieren Sie Integrationstests. Die meisten Features profitieren von beiden Typen.
Unit-Tests sollten für die gesamte Suite in unter 10 Sekunden abgeschlossen sein. Integrationstests können 1-5 Minuten dauern. Wenn Ihre Tests länger dauern, teilen Sie sie in parallele Jobs auf oder identifizieren Sie langsame Tests, die optimiert werden müssen. Schnelle Tests ermutigen Entwickler, sie häufig auszuführen.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.