Sie drücken eine kleine UI-Änderung vor dem Mittagessen aus. Sie sieht harmlos aus. Die Schaltflabel ändert sich, eine bedingte Renderung wird vereinfacht und ein Hilfs-Hook nimmt eine neue Zweigstruktur auf. Der Pull-Request ist sauber, die Überprüfung ist schnell und der Deploy geht raus.
Ein Stunde später meldet der Support, dass sich das Login auf einer Plattform nicht mehr funktioniert. Web sieht gut aus. Die Desktop-Shell hat einen veralteten Renderpfad. Die mobile Anwendung verhält sich anders nach einem asynchronen Zustandswechsel. Niemand hat es bemerkt, weil die code Tests hatten, aber nicht die richtigen Tests und definitiv kein zuverlässiges System um diese Tests herum.
Das Hauptproblem bei der Einheitstestung von React in Produktionsteams ist, dass die Schreibaufgabe von einigen funktionierenden Tests nicht schwer ist. Die Erstellung eines Suites, der Sie während von Refaktorisierungen, Release-Trainings, Hotfixes und Cross-Plattform-Packagings schützt, ist die schwierige Aufgabe. React-Anwendungen scheitern nicht daran, dass ein Team vergessen hat, wie man eine Funktion aufruft. Sie scheitern, weil die Tests sich auf Implementierungsdetails ausrichten, asynchrone Verhaltensweisen überdecken und CI die Testung wie ein Kontrollkästchen und nicht wie ein Release-Gateway behandelt. render()Moderne Einheitstestung von React funktioniert, wenn sie wie ein Sicherheitssystem funktioniert. Schnelle Feedbacks lokal. Deterministische Überprüfungen in CI. Klar definierte Grenzen um das, was in einer Einheitstestung gehört und was nicht. Das ist noch wichtiger, wenn die gleiche React-Anwendung über Browser, __CAPGO_KEEP_0__-Container oder Electron-Shell ausgeliefert wird.
Modern unit testing React works when it behaves like a safety system. Fast feedback locally. Deterministic checks in CI. Clear boundaries around what belongs in a unit test and what doesn’t. That matters even more when the same React codebase ships through browsers, Capacitor containers, or Electron shells.
Wenn Einheitstestung von React Ihr Bestes Sicherheitsnetz ist
- Was eine Einheitstestung schützen sollte
- Beginnen Sie mit einem vorhersehbaren Runner und Umfeld
- Testen Sie das Akkordeon wie ein Benutzer es verwendet
- Testen von benutzerdefinierten Hooks und Anwendungslogik
- Mastery fortschrittlicher Techniken: Mocking und Async
- Verbessern Sie die Testqualität und Strategie
- Integrierte Tests in einer Cross-Platform CI/CD Pipeline
Weshalb Unit-Testing von React Ihr bester Sicherheitsnetz ist
Einheitstests verdienen ihren Tribut, wenn sie den Fehler fangen, den Sie sicher nicht passieren lassen konnten. In React bedeutet das normalerweise, dass ein Komponente weiterhin renderet, aber das von Benutzern abhängige Verhalten geändert wurde. Ein deaktivierter Button wird klickbar. Ein Ladezustand wird nie gelöscht. Ein Ersatztext verschwindet nach einer Refaktorisierung. Diese Fehler sind klein in code und teuer in der Produktion.
Das React-Testing wurde in einer wichtigen Weise, als React Testing Library wurde zum mainstream-Modell für das Testen von Verhalten anstatt von Interna, wodurch Teams dazu gebracht wurden, Tests zu erstellen, die das Benutzerverhalten widerspiegeln, anstatt Komponenten-Props oder -Zustände, wie in der React Native-Testanleitung auf React Native-Testübersicht. Dieser Wechsel ist wichtig, weil React code ständig umgebaut wird. Hooks werden verschoben. Komponenten werden geteilt. Kontext wird eingeführt. Ein Test, der an der internen Struktur gebunden ist, bricht während gesunder Refaktorisierungen. Ein Test, der an sichtbarem Verhalten gebunden ist, überlebt normalerweise.
Was sollte ein Einheitstest schützen
Ein guter React-Einheitstest schützt einen kleinen Vertrag:
- Gespiegeltes Ausgabe: Sieht der Benutzer das richtige Text, Label, Zustand oder Fallback?
- Interaktionsverhalten: Ändert sich die Benutzeroberfläche richtig, wenn man klickt, tippt oder umschaltet?
- Grenzverhalten: Verhält sich das Komponente richtig, wenn es die erwarteten Eingaben, fehlende Daten oder einen Fehlerpfad erhält?
Ein schwacher Test schützt das falsche Ding:
- Komponenteninternes: Zustandsform, private Methoden, implementierungsbezogene Props
- Framework-Mechaniken: Wenn React eine Hook-Update intern genau so durchführte, wie Sie es erwartet haben
- Kindereigenschaften: Markups, die von nicht zu überprüfenden, verschachtelten Komponenten besessen werden
Praktische Regel: Wenn Sie das Komponenten ohne Änderung des Benutzererlebnisses oder -verhaltens umstrukturieren können, sollte der Test nicht geändert werden
Einheitstests befinden sich auch in einem umfassenderen Testsystem. Sie sollen nicht beweisen, dass die gesamte App funktioniert, von Anfang bis Ende. Sie sind die schnelle Schicht, die Regressionsfehler vor der Notwendigkeit eines Browser- oder Geräte-Level-Validierungspasses aufdeckt. Deshalb sind sie die erste Verteidigungslinie in jedem vernünftigen Stacks von automatisierten Tests für Produktionsanwendungen.
Für React-Teams, die häufig liefern, kommt die Zuversicht aus dieser Aufteilung der Arbeit. Einerheitstests fangen lokale Regressionsfehler schnell auf. Integrations-Tests überprüfen die Verbindungen. End-to-End-Tests bestätigen die kritischen Wege. Wenn Sie die Einerheitsschicht auslassen, muss alles langsamer unten mit zu viel Last belastet werden
Einrichten Ihres modernen React-Testumfelds
Ein brüchiges Testumfeld schafft flache Tests, bevor Sie eine einzelne Behauptung geschrieben haben. Viele Entwickler beschuldigen Jest, jsdom oder React, wenn das zugrunde liegende Problem eine inkonsistente Konfiguration auf verschiedenen lokalen Maschinen und CI ist. Die Lösung besteht darin, das Umfeld langweilig zu machen. Langweilig ist gut hier

Beginnen Sie mit einem vorhersehbaren Runner und Umfeld
Für eine moderne React-Anwendung, insbesondere eine mit Vite erstellt, sollte die Grundkonfiguration umfassen:
- Ein Testrunner: Jest bleibt gängig, insbesondere in älteren React-Codebasen und Enterprise-CI-Stacks.
- Ein browserähnliches Umfeld:
jsdomLassen Sie Komponententests den DOM-Ausgang rendern. - Testing Library-Utilitäten:
@testing-library/reactund@testing-library/jest-dom - Eine einzelne Setup-Eintrittspunkt: Ein einzelnes Datei, um Matcher und globale Mocks zu registrieren
Der Schlüsselworkflow, den Reacts Testleitfaden unterstreicht, ist einfach: Rendern Sie das Komponenten in einer jsdom-gestützten Umgebung, suchen Sie nach der UI mit Selektoren wie getByText oder getByRole, auslösen Sie eine Interaktion und bestätigen Sie den DOM-Wechsel, wie in der Beschreibung React-Test-DokumentationDieses Workflow bleibt nur dann vertrauenswürdig, wenn jede Maschine das gleiche Testumfeld verwendet.
Ein praktischer Jest-Einrichtung sieht normalerweise so aus:
// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
moduleNameMapper: {
'\\.(css|less|scss)$': 'identity-obj-proxy',
'^@/(.*)$': '<rootDir>/src/$1',
},
transform: {
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
},
};
Wenn Ihr Team stattdessen SWC verwendet, ist das in Ordnung. Der Punkt ist nicht der Transformer. Der Punkt ist Konsistenz. Wählen Sie einen Weg und standardisieren Sie ihn im Repository. Wenn Sie eine gute Begleitdokumentation für umfassende JavaScript-Testkonventionen benötigen, ist Capgo’s Ein Leitfaden für die Einheitstests in JavaScript ein nützliches Teamhandbuch.
Hinzufügen Sie die Einrichtungsdatei, auf die Ihr Suite angewiesen ist
Ein ordentlicher setupTests.js erspart viel wiederholten Lärm:
import '@testing-library/jest-dom';
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
Dieses Dokument ist der Ort, an dem Sie Umgebungsunterschiede einmal statt in zwanzig Testdateien lösen. Fügen Sie Mocks für APIs hinzu, auf die Ihre UI angewiesen ist, wie z. B. matchMedia, ResizeObserveroder IntersectionObserverwenn Ihre Komponentenbibliothek sie erwartet.
Entschuldigen Sie, ohne dies werden Entwickler globale Variablen ad hoc anpassen. Das führt zu inkonsistenten Tests und schwer zu verfolgenden Fehlern. Ein lokaler Lauf eines anderen Personen funktioniert, weil sie eine manuelle Mock-Funktion in einem Datei hinzugefügt haben. Der CI-Fehler tritt auf, weil die Einstellungen nicht geteilt wurden.
Halten Sie die lokalen und CI-Einstellungen in Einklang.
Die lokale Kommandozeilenanweisung sollte der CI-Kommandozeilenanweisung so nahe wie möglich entsprechen. Wenn Entwickler in Watch-Modus mit permissiven Einstellungen laufen, aber der CI eine strengere Konfiguration ausführt, erhalten Sie Überraschungsfehler nach dem Merge. Halten Sie Skripte explizit.
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:ci": "jest --runInBand --coverage"
}
}
Ein kurzer Leitfaden hilft neuen Teammitgliedern, sich schnell auf die gleiche Basis zu bringen:
Die wichtigste Einstellung ist die Disziplin bei den Standards. Legen Sie Alias in der Konfiguration ab. Legen Sie Umgebungs-Mocks in einer Einrichtungsdatei ab. Verwenden Sie jsdom für UI-Tests und eine leichtere Umgebung für reine Hilfsmittel, wenn möglich. Je weniger jede einzelne Testfunktion benötigt, desto zuverlässiger wird Ihr System.
Schreiben Sie bedeutungsvolle Komponenten-Tests.
Organisationen haben kein Problem, Tests zu schreiben. Sie haben ein Problem, Tests zu schreiben, die nach sechs Monaten noch Bedeutung haben.
Der Standardmuster für die Einheitstests von React-Komponenten ist immer noch das richtige: rendern Sie die Komponente, überprüfen Sie die Benutzeroberfläche mit benutzerzentrierten Selektoren, lösen Sie eine Interaktion aus und bestätigen Sie den resultierenden DOM-Änderungen, was die Tests von Implementierungsdetails wie Zustand oder Props fernhält, wie in der React-Testanleitung beschrieben. Das Geheimnis besteht darin, dieses Muster mit Zurückhaltung anzuwenden.
Testen Sie das Akkordeon wie ein Benutzer es verwendet.
Nehmen Sie ein grundlegendes Accordion Komponente. Sie rendern einen Button mit einem Titel. Der Inhalt des Panels beginnt versteckt. Klicken Sie auf den Button, um den Inhalt zu enthüllen und die Barrierefreiheit zu aktualisieren.
Das ist genug Verhalten für mehrere nützliche Tests:
- Die ursprüngliche Anzeige zeigt den Titel, aber nicht den Inhalt.
- Klicken Sie auf den Trigger, um den Inhalt zu enthüllen.
- Klicken Sie erneut, um ihn zusammenzufalten.
- Die Barrierefreiheitseigenschaften spiegeln den sichtbaren Zustand wider.
Das letzte Punkt wird oft übersehen. Wenn Ihre Komponente aria-expanded, aria-controlsverwendet, überprüfen Sie sie. Das sind keine Implementierungsdetails. Sie sind Teil des Benutzerfreundlichkeitsvertrags.
Die besten Komponententests lesen sich wie ein Fehlerbericht, den Sie nie erhalten möchten.
Wählen Sie Abfragen basierend auf der Absicht
React Testing Library bietet Ihnen mehrere Abfragemuster, aber sie sind nicht austauschbar. Die falsche Wahl macht die Tests laut oder irreführend.
| Abfrageart | Wenn das Element gefunden wird | Wenn das Element nicht gefunden wird | Beispiel für eine Verwendung |
|---|---|---|---|
getBy |
Gibt das Element sofort zurück | Würfelt sofort einen Fehler | Bestätigen Sie, dass ein Button oder ein Überschrift bereits auf dem Bildschirm ist |
queryBy |
Gibt das Element sofort zurück | Gibt null |
Bestätigen Sie, dass verstecktes Inhalt vor der Interaktion nicht existiert |
findBy |
Löst sich, wenn das Element erscheint | Nach einer Wartezeit abgelehnt | Behauptet, dass der asynchron geladene Inhalt nach einer Abfrage oder einer verzögerten Aktualisierung erscheint |
Ein einfaches mentales Modell hilft:
- Verwende
getByfür Dinge, die bereits existieren müssen. - Verwende
queryByfür Dinge, die noch nicht existieren dürfen. - Verwende
findBywenn sich die Benutzeroberfläche später ändert.
Wenn ein Test mit findBy für alles beginnt, bedeutet es normalerweise, dass der Autor sich nicht sicher ist, wann der Komponenten aktualisiert wird. Diese Unsicherheit wird später zu Flakiness.
A praktische Akkordeon-Beispiel
Hier ist ein repräsentatives Komponenten-Beispiel:
function Accordion({ title, children }) {
const [open, setOpen] = React.useState(false);
return (
<section>
<button
aria-expanded={open}
aria-controls="accordion-panel"
onClick={() => setOpen(prev => !prev)}
>
{title}
</button>
{open ? (
<div id="accordion-panel">
{children}
</div>
) : null}
</section>
);
}
Und hier ist die Form der Tests, die man behalten sollte:
import { render, screen, fireEvent } from '@testing-library/react';
test('renders the accordion title and hides content initially', () => {
render(<Accordion title="Shipping details">Delivery takes 3 days</Accordion>);
expect(screen.getByRole('button', { name: /shipping details/i })).toBeInTheDocument();
expect(screen.queryByText(/delivery takes 3 days/i)).not.toBeInTheDocument();
});
test('reveals content when the trigger is clicked', () => {
render(<Accordion title="Shipping details">Delivery takes 3 days</Accordion>);
fireEvent.click(screen.getByRole('button', { name: /shipping details/i }));
expect(screen.getByText(/delivery takes 3 days/i)).toBeInTheDocument();
});
test('updates aria-expanded when opened', () => {
render(<Accordion title="Shipping details">Delivery takes 3 days</Accordion>);
const button = screen.getByRole('button', { name: /shipping details/i });
expect(button).toHaveAttribute('aria-expanded', 'false');
fireEvent.click(button);
expect(button).toHaveAttribute('aria-expanded', 'true');
});
Was fehlt, ist genauso wichtig. Es gibt keine Behauptung gegen den internen Zustand. Keine Überprüfung, ob etwas aufgerufen wurde. Kein Snapshot des gesamten gerenderten Baums. Diese Tests würden die Wartung erhöhen, nicht die Zuversicht. setOpen Eine paar Gewohnheiten machen Komponententests stärker:
Präferieren Sie role-basierte Abfragen:
- Tasten, Überschriften, Dialoge, Warnungen und Eingabefelder sollten normalerweise über ihre Rolle gefunden werden. Behalten Sie jeden Test eng:
- Ein Benutzerinteraktionsverhalten pro Test hält die Fehlermeldungen lesbar. Bennen Sie Tests nach Ergebnissen:
- “aktualisiert aria-expanded, wenn geöffnet” ist viel nützlicher als “funktioniert richtig.” Präferieren Sie role-basierte Abfragen: Tasten, Überschriften, Dialoge, Warnungen und Eingabefelder sollten normalerweise über ihre Rolle gefunden werden.
Wenn ein Komponente über die DOM schwer zu testen ist, offenbart das oft ein Designproblem. Vielleicht versteckt sie den Zustand an falschem Ort. Vielleicht fehlt es an semantischer Markierung. Gute Tests drängen Teams oft zu besseren Komponenten.
Zusätzliche Hooks und Anwendungslogik testen
React-Anwendungen verbergen eine Menge wichtiger Verhaltensweisen außerhalb von Komponenten. Zustandsübergänge leben in Hooks. Validierung und Formatierung leben in Hilfsfunktionen. Die Datenformierung findet oft vor dem ersten Rendern statt. Wenn Sie nur sichtbare Komponenten testen, werden Sie einen großen Teil der code übersehen, der den Produktionsverhalten noch brechen kann.
Hooks benötigen eine React-fähige Umgebung
Ein benutzerdefinierter Hook benötigt noch immer React, um korrekt zu funktionieren, also testen Sie ihn mit renderHook und umfassen Sie Zustandsänderungen in act().
Ein kleiner useToggle Hook ist ein gutes Beispiel:
import { useState, useCallback } from 'react';
export function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
const toggle = useCallback(() => setValue(current => !current), []);
return { value, toggle };
}
Sein Test sollte sich auf den öffentlichen Vertrag konzentrieren:
import { renderHook, act } from '@testing-library/react';
import { useToggle } from './useToggle';
test('returns the initial value', () => {
const { result } = renderHook(() => useToggle(true));
expect(result.current.value).toBe(true);
});
test('toggles the value', () => {
const { result } = renderHook(() => useToggle(false));
act(() => {
result.current.toggle();
});
expect(result.current.value).toBe(true);
});
Dieser Test ist nützlich, weil der Hook selbst die Einheit ist. Sie testen nicht die React-Internen. Sie verifizieren das externe Verhalten des Hooks.
Für Produktteams, die wiederholbar UI oder Feature-Primitiven bauen, ist dieses Muster sehr wichtig. Hooks werden oft als Schnittstelle zwischen Apps, Design-Systemen oder internen Werkzeugen verwendet. Wenn Sie wiederholbare Verhaltensweisen mit kommerziellem Zweck entwerfen, sind die Ressourcen zu Hooks für Makers-Produkte Kann dabei Hooks als standardisierte Bausteine anstatt nur als Implementierungsdetails darstellen.
Reine Logik sollte in Tests rein bleiben.
Es ist nicht alles erforderlich jsdom, React oder Testing Library. Wenn eine Funktion rein ist, testen Sie sie mit plain Jest in einem Node-Umgebung.
Beispiel:
export function formatDisplayName(firstName: string, lastName: string) {
return `${firstName.trim()} ${lastName.trim()}`.trim();
}
Diese Test sollte einfach sein:
import { formatDisplayName } from './formatDisplayName';
test('joins and trims both names', () => {
expect(formatDisplayName(' Ada ', ' Lovelace ')).toBe('Ada Lovelace');
});
test('handles a missing last name', () => {
expect(formatDisplayName('Ada', '')).toBe('Ada');
});
Der Gewinn hier ist Geschwindigkeit und Klarheit. Wenn eine Funktion keinen Renderbaum benötigt, geben Sie ihr keinen. React-spezifische Werkzeuge fügen Überhead hinzu. Halten Sie Geschäftslogik-Tests klein, schnell und nahe an der Funktion, die sie überprüfen.
Ein praktischer Split funktioniert gut:
- Hooks: Verwenden Sie
renderHook,act()und Wrapper-Provider, wenn erforderlich. - Werkzeuge: Verwenden Sie plain Jest und keine DOM.
- Zustandsbasierte Schnittstellenlogik: Ziehen Sie sie in testbare Hilfsfunktionen, wenn der Komponententest zu viel tut.
Teams überfüllen Komponententests oft mit Logikannahmen, die tiefer in der Stacks liegen. Wenn Sie diese Logik herausziehen, erhalten Sie zwei Vorteile. Der Komponententest wird sauberer, und der Logiktest wird schneller.
Meisterung fortschrittlicher Techniken Mocking und Async
Die meisten unzuverlässigen React-Suiten brechen an zwei Stellen. Sie brechen an Grenzen von Abhängigkeiten und sie brechen um Zeit.
Deshalb ist das Asynchron-Testen und das Mocking die Grenze zwischen einem Spielzeug-Test-Suite und einer, die Sie vor der Veröffentlichung vertrauen können. Eine Analyse gibt an, dass 46,5% der Testflakigkeit auf Umgebungs- oder Ressourcenbezogene Probleme wie asynchrone Timing zurückzuführen ist um in dieser React-Einheitstestanalyse. In React-Anwendungen entspricht dies direkt den Zustandsübergängen, der verzögerten Darstellung, der Netzwerk-gesteuerten Benutzeroberfläche und den Tests, die statt dessen deterministisch warten.

Mocken Sie die Grenze, nicht jede Schicht
Der schnellste Weg, einen irreführenden Test zu schreiben, besteht darin, die Hälfte Ihres Komponentenbaums zu mocken und dann zu behaupten, dass Ihre eigenen Mocks funktioniert haben.
Für eine Komponente, die Kontodaten abruft, mocken Sie den Netzwerkclient oder den API-Modul. Mocken Sie nicht den Hook, das Kinderelement, den Ladezustand und drei Hilfsfunktionen, es sei denn, der Test benötigt tatsächlich eine Isolation an diesen Schnittstellen.
Verwenden Sie diese Regelsatz:
- Mocken Sie externe Dienste: HTTP-Clients, Analysedaten, Browser-only-APIs, native Brücken
- Mocken Sie unbeständige Plattform-APIs:
matchMedia, Timer, Electron-Vorkomponenten, Capacitor-Plugins, wenn sie in jsdom nicht verfügbar sind - Vermeiden Sie das Mocken Ihrer eigenen Interna standardmäßig: Benutzerdefinierte Hooks, einfache Kinder, lokale Hilfsfunktionen
Wenn ein Test erfolgreich ist, weil alle schwierigen Teile durch Fakes ersetzt wurden, hat er Ihnen nicht viel Vertrauen in die Freigabe gebracht.
Für Teams, die Beispiele und Muster rund um Runner-APIs und Capgo suchen Testtutorials ist eine praktische Referenzbibliothek, insbesondere bei der Einarbeitung von Entwicklern, die React kennen, aber noch nicht die Testmechanik.
Async-Tests scheitern, wenn die Zeitung vage ist
Async-Fehler kommen in der Regel von einem der folgenden Fehler:
- Der Test behauptet zu früh.
- Der Test wartet mit willkürlichen Zeitschaltungen.
- Der Komponenten aktualisiert sich mehr als einmal, aber der Test modelliert nur eine Übergang.
Ein stabiler Async-Test hat normalerweise diese Form:
test('shows user details after data loads', async () => {
render(<UserProfile userId="42" />);
expect(screen.getByText(/loading/i)).toBeInTheDocument();
expect(await screen.findByText(/account owner/i)).toBeInTheDocument();
});
Oder, wenn Sie auf eine bestimmte Bedingung warten müssen:
await waitFor(() => {
expect(screen.getByRole('alert')).toBeInTheDocument();
});
Verwenden Sie findBy wenn die Erscheinung eines Elements das Ereignis ist, auf das Sie achten. Verwenden Sie waitFor wenn die Bedingung breiter ist oder der Zustand nicht mit einer einzelnen Abfrage ausgedrückt werden kann. Vermeiden Sie setTimeout in Tests, es sei denn, Sie testen explizit das Timer-Verhalten und verwenden fiktive Timer.
React's Testumgebung erwartet auch, dass Sie die Semantik bei Updates respektieren. act() Testing Library handhabt einen großen Teil davon für Sie, aber wenn Sie den Zustand manuell steuern oder Timer vorwärts setzen, müssen Sie immer noch darüber nachdenken, wann Updates abgeschlossen sind.
Wissen, welches Mocking-Tool Sie greifen sollten.
Different Mocking-Tools lösen unterschiedliche Probleme:
| Tool | Beste Verwendung | Häufiger Fehler |
|---|---|---|
jest.fn() |
Fiktive Callbacks oder injizierte Funktionen | Es verwendet, um einen ganzen Modul zu ersetzen, wenn ein einfacher Callback ausreicht |
jest.spyOn() |
Eine Methode auf einem realen Objekt oder Modul beobachten oder überschreiben | Das ursprüngliche Implementierung vergessen |
jest.mock() |
Ersatz einer Modulabhaengigkeit an der Importgrenze | Große Module durch Voreinstellung mocken und damit bedeutungsvolle Verhalten verlieren |
Beispielhilfe:
- Greifen Sie nach
jest.fn()wenn ein Komponente einenonSubmitEigenschaften - Verwenden Sie
jest.spyOn()wenn Sie das Verhalten einerconsole.errorSpeicherungsmethode oder eines exportierten API Aufrufs überprüfen müssen - Verwenden Sie
jest.mock()wenn die Importierung eines Moduls sonst I/O, native code, oder Verhalten außerhalb der Einheitengrenze auslaufen würde
Ein fortgeschrittenes Gebiet, das viele Anleitungen vernachlaessigen, ist die Fehlerpfad-Testung im modernen React. Fehlergrenzen, verzögerte Zustandsänderungen und asynchrone Ersatz-UIs verdienen erste-Klasse-Tests, nicht nur den "gluecklichen Weg"-Klickbeispiel. Wenn ein Kind einen Fehler werfen sollte, behaupten Sie die Ersatz-UI. Wenn eine Anfrage fehlschlägt, behaupten Sie den sichtbaren Recovery-Zustand. Wenn ein Button während der Ladezeit deaktiviert ist, behaupten Sie das auch. Das sind die Fehler, die die Benutzer merken.
Qualität und Strategie der Tests verbessern
Viele Teams verfolgen immer noch die Abdeckung wie es dasselbe wäre wie Vertrauen. Es ist nicht.
Man kann ein Abdeckungsziel erreichen und trotzdem diejenigen Rückschritte verpassen, die zählen. Ein vollständiges Set an oberflächlichen Behauptungen, breiten Szenarios und mockten Interna erzeugen den Eindruck von Sicherheit, während sie gleichzeitig die Wartungskosten erhöhen.

Abdeckung ist ein Kartenbild, nicht das Ziel
Abdeckungsberichte sind nützlich, wenn sie eine Frage beantworten: welche kritischen Wege haben noch keine Schutz?
Sie sind nicht nützlich, wenn sie Entwickler dazu bringen, trivialen Wrapper, statischen Markup oder eine-Linien-Übertragungsdateien nur um einen Prozentsatz zu testen. Behandeln Sie die Abdeckung als Entdeckungstool. Wenn der Authentifizierungsstatus, die Abrechnungsaktionen, die Feature-Flags oder die Aktualisierungsanfragen keine Tests haben, ist das ein Signal. Wenn ein präsentatives ikonisches Komponenten keine Tests hat, ist das normalerweise nicht.
Eine gesunde Überprüfungsfrage ist einfach: reduziert diese Test die Auslieferungsrisiken?
- Ja: Es überprüft die Benutzersichtbarkeit auf einem kritischen Weg.
- Vielleicht: Es schützt die Geschäftslogik, die leicht während einer Überarbeitung gebrochen werden kann.
- Nein: Es stellt Implementierungsdetails oder dupliziert den Wert eines anderen Tests fest.
Was nicht getestet werden sollte
Viele React-Anleitungen geben nicht genügend Aufmerksamkeit der Unterlassung. Diese Lücke ist wichtig, da übermäßiges Mocken und Implementierungs-Detail-Testen brüchige Suites erzeugen, die zwar bestehen, aber die Benutzererfahrung immer noch bricht, wie in der BrowserStack-Anleitung zu was nicht getestet werden sollte in React.
Übergehen oder stark einschränken Sie diese Muster:
- Internes Zustandsfeststellung: Testen Sie nicht
isOpendirekt, wenn Sie testen können, ob das Panel geöffnet wurde. - Framework-Verhalten: Testen Sie nicht, dass React einen Effekt aufgerufen hat. Testen Sie das Ergebnis dessen, was der Effekt ändert.
- Drittanbieter-Bibliotheksinhalte: Testen Sie Ihre Integration mit einem Datumsauswahlfeld oder einem Router, nicht mit der eigenen Rendereigenschaften der Bibliothek.
- Über-brochene Einheiten: Wenn Sie jedes Kind und Hilfsmittel gemockt haben, testen Sie möglicherweise keine mehrwertigen Verhaltensweisen.
Schlechte Tests sind schlimmer als fehlende Tests, wenn sie Refaktorisierungen blockieren und trotzdem keine Produktionsfehler erkennen.
Eine nützliche Heuristik ist die Eigentümerschaft von Grenzen. Testen Sie, was Ihr code besitzt. Testen Sie nicht, was React, der Browser oder eine reife Bibliothek bereits besitzt, es sei denn, Ihre Integrationslayer ändert den Vertrag.
Wo Snapshots helfen und wo sie schaden
Snapshots sind nicht nutzlos. Sie werden einfach leicht missbraucht.
Verwenden Sie sie sparsam für Komponenten mit stabilen, einfachen Ausgaben, bei denen eine breite strukturelle Differenz bedeutungsvoll ist. Vermeiden Sie sie für interaktive oder hochdynamische Komponenten, da sie Lärm erzeugen. Entwickler lesen sie nicht mehr und beginnen, sie reflexiv zu aktualisieren.
Bessere Alternativen existieren normalerweise:
- Für bedingte Rendern, behaupten Sie die Präsenz oder Abwesenheit von Schlüsseltext.
- Für visuelle Zustandsänderungen, behaupten Sie die Rolle, Bezeichnung oder Attribut, das zählt.
- Für Fehler und Fallbacks, behaupten Sie den tatsächlichen Fehlermeldung oder Warnbereich.
Wenn Ihr Team ein umfassenderes Qualitätssicherungsverfahren benötigt, das über Einheitstests hinausgeht, ist ein solides Begleiter ein Qualitätssicherungsworkflow für Apps der Tests, Release-Überprüfungen und Rollback-Planung als ein System behandelt. Das ist der geistige Wandel, der die Testqualität am schnellsten verbessert. Hört auf, nachzudenken, wie viele Tests Sie haben. Beginnen Sie stattdessen damit, zu fragen, welche Fehler noch auf die Benutzer zukommen könnten.
Integrieren von Tests in eine Cross-Plattform CI/CD Pipeline
Ein Test-Suite, die nur auf einem Entwickler-Laptop läuft, ist nur eine Empfehlung und kein Kontrollpunkt.
Die Suite wird erst dann operativ, wenn jeder Pull-Request die gleichen Überprüfungen in einem sauberen Umfeld durchführt und die Mergen blockiert, wenn diese Überprüfungen fehlschlagen. Das klingt offensichtlich, aber viele Teams lassen kritische Lücken bestehen. Tests werden manuell durchgeführt. Abdeckungsberichte sind optional. Verpackungs- und Release-Jobs beginnen, bevor die Test-Jobs abgeschlossen sind. Das ist der Weg, auf dem kleine UI-Regressionen in größere Release-Fehler eintauchen.

Ein Pull-Request sollte jeden Mal den gleichen Gate auslösen
Um React-Einheitstests wie ein Sicherheitsnetz zu machen, benötigt CI ein paar Grundlagen:
- Ausführen auf jedem Pull-Request
- Installieren von Abhängigkeiten aus Lockfile
- Verwenden Sie den gleichen Test-Befehl jeden Mal
- Versagen Sie schnell bei Testfehlern
- Veröffentlichen Sie Artefakte nur, nachdem die Tests erfolgreich sind
Dies ist das Kernstück kontinuierlicher Bereitstellung für App-Teams. Bauen Sie Vertrauen vor der Veröffentlichung, nicht danach
Eine einfache GitHub Actions-Aufgabe reicht für viele Teams aus:
name: test
on:
pull_request:
push:
branches:
- main
jobs:
react-tests:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm run test:ci
Dies ist nicht besonders, und das ist der Punkt. Die stärksten Pipelines sind meistens die überraschendsten.
Weshalb dies für Capacitor und Electron wichtiger ist
Cross-platform-React-Anwendungen tragen mehr Veröffentlichungsrisiko als Browser-Only-Anwendungen, weil die gleiche UI code oft in verschiedenen Containern mit unterschiedlichen Laufzeitannahmen geliefert wird.
Einige Beispiele zeigen, wo Pipelines helfen:
- Capacitor-Anwendungen: Web code mag lokal erfolgreich sein, aber fehlschlagen, wenn ein Plugin-Brücke, Offline-Zustand oder App-Lifecycle-Randfall das Verhalten nach dem Packen ändert.
- Elektron-Anwendungen: Eine Renderer-Komponente kann auf Präloader-APIs, Fenster-Meldungen oder Desktop-spezifische Zustände angewiesen sein, die in einer reinen Browser-Testumgebung nicht existieren, es sei denn, sie werden absichtlich nachgemacht.
- Gemeinsame Release-Trainings: Ein schlechter Bundle kann auf mehrere Ziele auswirken, wenn Ihr Bereitstellungsprozess die Veröffentlichung nicht engmaschig überwacht.
Deshalb sollten Einheitstests vor der Verpackungslaufe laufen und die Verpackungslaufe sollten vor den Verteilungslaufen laufen. Jeder Schritt verringert das Risiko. Einheitstests fangen lokale Rückschritte schnell ein. Die Plattform-Verpackung überprüft die Umgebungsannahmen. Die manuelle Genehmigung oder die stufenweise Veröffentlichung handhabt die letzte Veröffentlichungsvertraulichkeit.
Eine praktische GitHub Aktionen-Workflow
Eine reifere Pipeline teilt normalerweise Verantwortlichkeiten:
- Testaufgabe: Schnelle Einheitstests und Hook-Tests
- Build-Aufgabe: Nur nach erfolgreichen Tests eine Produktionsverbindung erstellen
- Paket-Aufgabe: Capacitor Synchronisierung, Electron-Paketierung oder Artefaktbündelung
- Release-Auftrag: Veröffentlichen Sie nur von genehmigten Branches oder Tags
Für Teams, die live Updates an Capacitor oder Electron-Anwendungen liefern, ist dies der Punkt, an dem die Release-Tooling relevant wird. Eine Option in diesem Workflow ist Capgo, die signierte Web-Bundles für CapacitorJS- und Electron-Anwendungen mit Rollback-Unterstützung und kanalbasierten Rollout-Kontrollen veröffentlicht. In der Praxis bedeutet dies, dass Ihr React-Testauftrag als erste harte Schranke vor der Veröffentlichung von Web-Bundles in die Staging- oder Produktionslieferung fungieren kann.
Die operative Regel ist einfach. Lassen Sie die Release-Infrastruktur nicht die schwachen Tests kompensieren. Verwenden Sie die Release-Infrastruktur nachverlässlichen Tests, die bereits schlechte Änderungen ausgeschlossen haben.
Ein zuverlässiges Testsystem ändert das Verhalten der Teams. Ingenieure fusionieren mit weniger Hesitation. Rezensenten konzentrieren sich auf Randfälle anstatt die Grundlagen manuell nachzuruntern. Release-Manager behandeln jeden Deploy nicht mehr wie ein Wettbewerb. Das ist das Ergebnis eines guten Unit-Testens von React.
Wenn Ihr Team React über Capacitor oder Electron liefert, hängt die Release-Sicherheit von mehr als grünen lokalen Tests ab. Capgo bietet Teams einen kontrollierten Weg, signierte Web-Updates zu veröffentlichen, Zielrollout-Kanäle anzusteuern und schlechte Bundles ohne Wartezeit auf die Store-Überprüfung zurückzurufen, was sich natürlich hinter einer CI-Pipeline einfügt, die bereits die Einhaltung von Unit-Tests vor der Bereitstellung erfordert.