Sie drücken vor dem Mittagessen eine kleine UI-Änderung aus. Sie wirken unschuldig. Eine Schaltetikett-Bezeichnung ändert sich, eine bedingte Darstellung wird vereinfacht und ein Hilfs-Hook greift eine neue Zweig-Struktur auf. Der Pull-Request ist sauber, die Überprüfung ist schnell und die Bereitstellung geht raus.
Ein Stunde später meldet sich der Support und berichtet, dass sich das Login auf einer Plattform nicht mehr funktioniert hat. Web sieht gut aus. Die Desktop-Shell hat einen veralteten Render-Weg. Die mobile Anwendung verhält sich anders, nachdem sich ein asynchroner Zustandswechsel ereignet hat. Niemand hat es bemerkt, weil die code Tests vorhanden waren, aber nicht die richtigen Tests und definitiv kein zuverlässiges System um diese Tests herum.
Das ist das Hauptproblem mit der Einheitstestung von React in Produktions-Teams. Ein paar laufende Tests zu schreiben, ist nicht schwer. Ein Test-Suite zu bauen, die dich auch während von Refaktorisierungen, Release-Trainings, Hotfixes und Cross-Plattform-Packagings schützt, ist das schwierige Teil. React-Anwendungen scheitern nicht, weil ein Team vergessen hat, wie man render()Sie scheitern, weil sich die Tests in Richtung Implementierungs-Details bewegen, asynche Verhaltensweisen überdeckt werden und die CI-Testung wie ein Checkbox und nicht wie ein Release-Gate behandelt wird.
Die moderne Einheitstestung von React funktioniert, wenn sie wie ein Sicherheitssystem funktioniert. Schnelle Feedbacks lokal. Deterministische Überprüfungen in der CI. Klare Grenzen um das herum, was in einen Einheitstest gehört und was nicht. Das ist noch wichtiger, wenn die gleiche React-Anwendung durch Browser, Capacitor-Container oder Electron-Shellen ausgeliefert wird.
Inhaltsverzeichnis
- Weshalb die Einheitstestung von React dein bester Sicherheitsnetz ist
- Einstellung Ihrer modernen React-Testumgebung
- Schreiben Sie bedeutungsvolle Komponententests
- Testen von benutzerdefinierten Hooks und Anwendungslogik
- Mastery fortgeschrittener Techniken: Mocking und Async
- Qualität und Strategie der Tests verbessern
- Integrierte Tests in einem Cross-Platform CI/CD Pipeline einbinden
Warum Unit-Testing von React der beste Sicherheitsnetz ist
Einheitstests verdienen ihren Lohn, wenn sie den Fehler fangen, den Sie sicher waren, dass er nicht passieren kann. In React bedeutet das normalerweise, dass ein Komponente weiterhin renderet, aber das Verhalten, auf das sich der Benutzer verlässt, sich geändert hat. Ein deaktiver Button wird klickbar. Ein Ladezustand wird nie gelöscht. Eine Ersatzmeldung verschwindet nach einer Überarbeitung. Diese Fehlfälle sind klein in code und teuer in der Produktion.
Die React-Testung hat sich in einer wichtigen Weise geändert, als Die React Testing Library wurde zum mainstream-Modell für die Testung von Verhalten anstatt von Interna, was Teams dazu drängt, Tests zu schreiben, die das Benutzer-Verhalten widerspiegeln, anstatt Komponenten-Props oder -Zustände, wie im React Native-Testleitfaden auf React Native-Testübersichtbeschrieben wird. Diese Veränderung 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 Überarbeitungen zusammen. Ein Test, der an sichtbarem Verhalten gebunden ist, überlebt normalerweise.
Was ein Einheitstest schützen sollte
Ein guter React-Einheitstest schützt einen kleinen Vertrag:
- Rendertes Ausgabe: Gibt der Benutzer das richtige Text, Label, Zustand oder Ersatz an?
- Interaktionsverhalten: Gibt das Klicken, Tippen oder Umstellen des UI korrekt?
- Grenzwert-Handling: Verhält sich das Komponente korrekt, wenn es die erwarteten Eingaben, fehlende Daten oder einen Fehlerpfad erhält?
Ein schwacher Test schützt das falsche Ding:
- Komponenten-Internes: Zustandsform, private Methoden, nur für die Implementierung bestimmte Props
- Framework-Mechaniken: Ob React eine Hook im genauen Weg aktualisiert, wie Sie es innerhalb der Komponente erwartet haben
- Kinder-Details: Markup, das von untergeordneten Komponenten besitzt, die Sie hier nicht überprüfen möchten
Praktische Regel: Wenn Sie die Komponente ohne Änderung des Benutzererlebnisses oder der Funktionalität umstrukturieren können, sollte der Test auch nicht geändert werden
Einheiten-Tests sitzen auch in einem umfassenderen Testsystem. Sie versuchen nicht, das gesamte Anwendungsprogramm zu beweisen. Sie sind die schnelle Schicht, die Regressionsfehler vor der Notwendigkeit eines Browser-Level-Tests oder einer Geräte-Level-Validierung durchführt. Deshalb sind sie die erste Verteidigungslinie in jeder vernünftigen Stacks von Tests Automatisierte Tests für Produktionsanwendungen.
Für React-Teams, die häufig liefern, kommt der Vertrauen durch diese Aufteilung der Arbeit. Einheiten-Tests fangen lokale Rückschläge schnell ein. Integrationstests überprüfen die Verbindungen. End-to-End-Tests bestätigen die kritischen Wege. Springen Sie die Einheitsschicht aus und alles langsamer flussabwärts muss zu viel Gewicht tragen.
Einstellung Ihrer modernen React-Umgebung für Tests
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 inkonsistente Konfigurationen auf lokalen Maschinen und CI ist. Die Lösung besteht darin, die Umgebung langweilig zu machen. Langweilig ist gut hier.

Beginnen Sie mit einem vorhersehbaren Runner und Umgebung
Für eine moderne React-Anwendung, insbesondere eine, die mit Vite erstellt wurde, sollte die Basis-Einstellung umfassen:
- Eine Testrunner: Jest bleibt gängig, insbesondere in älteren React-Codebasen und Unternehmens- CI-Stacks.
- Eine browserähnliche Umgebung:
jsdomlässt Komponententests DOM-Ausgaben rendern. - Testing Library-Utilitäten:
@testing-library/reactund@testing-library/jest-dom - Ein einzelner Setup-Einstiegspunkt: Ein einzelner Datei, um Matcher und globale Mocks zu registrieren
Die wichtigste Arbeitsweise, die sich die Testleitlinien von React bestätigen, ist einfach: Das Komponenten in einer jsdom-gestützten Umgebung rendern, die UI mit Selektoren wie getByText oder getByRole, Interaktion auslösen und die DOM-Änderung überprüfen, wie in der Dokumentation zu React-Testsbeschrieben. Diese Arbeitsweise bleibt nur vertrauenswürdig, wenn jede Maschine das gleiche Testumfeld verwendet.
Ein praktischer Jest-Setup 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',
},
};
If your team uses SWC instead of Babel, that’s fine. The point isn’t the transformer. The point is consistency. Choose one path and standardize it in the repo. If you want a good companion reference for broader JavaScript testing conventions, Capgo’s __CAPGO_KEEP_0__-Leitlinie für Einheitstests in JavaScript ein nützliches Teamhandover-Dokument.
Fügen Sie die Konfigurationsdatei hinzu, auf die Ihr Suite angewiesen ist
Ein ordnungsgemäßes setupTests.js sichert eine Menge wiederholter Lärm ab:
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(),
})),
});
In dieser Datei lösen Sie Umgebungsunterschiede einmal statt in zwanzig Testdateien. Fügen Sie Mocks für APIs hinzu, auf die Ihre UI angewiesen ist, wie z.B. matchMedia, ResizeObserver, oder IntersectionObserver, wenn Ihre Komponentenbibliothek sie erwartet.
Ohne dies werden Entwickler globale Variablen ad hoc anpassen. Das führt zu inkonsistenten Tests und schwer zu verfolgenden Fehlern. Ein lokaler Lauf eines Entwicklers funktioniert, weil er eine manuelle Mock-Datei in einem File hinzugefügt hat. Der CI-Fehler tritt auf, weil die Konfiguration nicht geteilt wurde.
Halten Sie lokale und CI-Verhaltensweisen in Einklang
Der lokale Befehl sollte dem CI-Befehl 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, die gleiche Basis schnell zu erreichen:
Die wichtigste Konfigurationsentscheidung ist die Disziplin bei den Standards. Legen Sie Alias in der Konfiguration ab. Legen Sie Umgebungs-Mocks in einer Konfigurationsdatei ab. Verwenden Sie jsdom für UI-Tests und eine leichte Umgebung für reine Utilities, wenn möglich. Je weniger jede einzelne Testdatei eigene Verhaltensweisen benötigt, desto zuverlässiger wird Ihr System.
Komponenten-Tests schreiben, die einen Sinn ergeben
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: Die Komponente rendern, die Benutzeroberfläche mit benutzerzentrierten Selektoren abfragen, eine Interaktion auslösen und die resultierende DOM-Änderung überprüfen, das die Tests von Implementierungsdetails wie Zustand oder Props fernhält, wie in der React-Testanleitung beschrieben. Der Trick besteht darin, dieses Muster mit Beschränkung anzuwenden.
Ein Akkordeon wie ein Benutzer es verwendet
Eine grundlegende Accordion Komponente. Sie rendern einen Button mit einem Titel. Der Inhalt des Panels beginnt versteckt. Durch Klicken auf den Button wird der Inhalt sichtbar und die Barrierefreiheit wird aktualisiert.
Das reicht aus, um mehrere nützliche Tests zu schreiben:
- Die Initialdarstellung zeigt den Titel, aber nicht den Inhalt.
- Klicken Sie auf den Trigger, um den Inhalt zu enthüllen.
- Klicken Sie erneut, um ihn zusammenzufassen.
- Zugänglichkeitsattribute spiegeln den sichtbaren Zustand wider.
Das letzte Punkt wird oft übersehen. Wenn Ihr Komponente aria-expanded, aria-controls, oder eine rolengestützte Struktur verwendet, überprüfen Sie sie. Das sind keine Implementierungsdetails. Sie sind Teil des Benutzerinterface-Kontrakts.
Die besten Komponententests lesen sich wie ein Fehlerbericht, den Sie nie erhalten möchten.
Wählen Sie die Abfragen basierend auf der Absicht.
React Testing Library bietet Ihnen mehrere Abfragesätze, 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 Verwendungsfall |
|---|---|---|---|
getBy | Gibt das Element sofort zurück | Würft eine Fehlermeldung sofort aus | Behauptet, dass ein Button oder ein Titel bereits auf dem Bildschirm sein sollte |
queryBy | Gibt das Element sofort zurück | Gibt zurück null | Behauptet, dass versteckte Inhalte vor der Interaktion nicht existieren sollten |
findBy | Löst sich auf, wenn das Element erscheint | Würft einen Fehler nach einer Wartezeit aus | Behauptet, dass asynchron geladener Inhalt nach einem Fetch oder einer verzögerten Aktualisierung erscheint |
Ein einfaches mentales Modell hilft:
- Verwende
getByfür Dinge, die bereits existieren müssen - Verwenden Sie
queryBy__CAPGO_KEEP_0__ für Dinge, die noch nicht existieren dürfen. - Verwenden Sie
findBywenn sich die Benutzeroberfläche später ändert.
Wenn ein Test mit findBy __CAPGO_KEEP_0__ 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.
Ein praktisches Beispiel für einen Akkordeon-Stecker
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 von 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 setOpen __CAPGO_KEEP_0__ aufgerufen wurde. Kein Snapshot des gesamten gerenderten Baums. Diese Tests würden die Wartung und nicht die Zuversicht erhöhen.
Einige Gewohnheiten machen die Komponenten-Tests stärker:
- Benutze rollenbasierte Abfragen: Schaltflächen, Überschriften, Dialoge, Warnungen und Eingabefelder sollten normalerweise über ihre Rolle gefunden werden.
- Halte jede Testanweisung eng: Eine Benutzerinteraktion pro Test hilft bei fehlgeschlagenen Tests, die Ergebnisse zu verstehen.
- Benenne Tests nach Ergebnissen: “aktualisiert aria-expanded, wenn geöffnet” ist viel nützlicher als “funktioniert richtig.”
Wenn ein Komponente schwer zu testen ist, zeigt das oft ein Designproblem an. Vielleicht versteckt sie den Zustand an falschem Ort. Vielleicht fehlt es an semantischer Markierung. Gute Tests drängen Teams oft zu besseren Komponenten.
Testen von benutzerdefinierten Hooks und Anwendungslogik
React-Apps 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 Rendern statt. Wenn man nur sichtbare Komponenten testet, verpasst man einen großen Teil der code , die den Produktionsverhalten noch brechen können.
Hooks benötigen eine React-fähige Umgebung
Ein benutzerdefinierter Hook benötigt noch immer React, um korrekt zu funktionieren, daher testen Sie ihn mit renderHook und um den Zustandsänderungen in einer Umhüllung zu schützen act().
Ein kleiner useToggle Ein Haken 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 Haken selbst die Einheit ist. Sie testen nicht die internen Reaktionsdetails. Sie überprüfen die externen Verhaltensweisen des Hakens.
Für Produktteams, die wieder verwendbare UI oder Funktionsprimitive erstellen, ist dieses Muster sehr wichtig. Haken werden oft als Schnittstelle zwischen Anwendungen, Design-Systemen oder internen Werkzeugen verwendet. Wenn Sie wieder verwendbare Verhaltensweisen mit kommerziellem Zweck entwerfen, können Ressourcen zu Haken für Produkte von Makers Helfen, Haken als produktisierte Bausteine und nicht nur als Implementierungsdetails zu betrachten.
Reine Logik sollte in Tests rein bleiben
Nicht alles benötigt jsdomReact 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();
}
Dieser Test sollte extrem 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');
});
Die Gewinn hier ist Geschwindigkeit und Klarheit. Wenn eine Funktion kein renderter Baum benötigt, gebe es keinen. React-spezifische Werkzeuge fügen Überhead hinzu. Halte Geschäftslogik-Tests klein, schnell und nahe bei der Funktion, die sie überprüfen soll.
Ein praktischer Split funktioniert gut:
- Hooks: Verwende
renderHook,act(), und Wrapper-Provider, wenn nötig. - Utilities: Verwende plain Jest und keine DOM.
- Zustandsbehaftete Schnittstellenlogik: Ziehe sie in testbare Hilfsmittel, wenn der Komponententest zu viel tut.
Teams überfüllen Komponententests oft mit Logikannahmen, die tiefer in der Stacks liegen. Wenn du diese Logik herausziehst, hast du zwei Vorteile. Der Komponententest wird sauberer, und der Logiktest wird schneller.
Mastern Sie fortgeschrittene 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 herum.
That ist der Grund, warum asynchrone Tests und Mocks die Grenze zwischen einem Spielzeug-Test-Suite und einem, den Sie vor der Veröffentlichung vertrauen können, darstellen. Eine Analyse gibt 46,5 % der Testflakigkeit auf Umgebungs- oder Ressourcenbezogene Probleme wie asynchrone Timing zurück 46,5 % der Testflakigkeit werden Umgebungs- oder Ressourcenbezogene Probleme wie asynchrone Timing zugeschrieben in dieser Analyse zu React-Einheitstests. 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.

Mocke die Grenze, nicht jede Schicht
Die schnellste Möglichkeit, 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 ein Komponenten, das Konten-Daten abruft, mocke den Netzwerk-Client oder API-Modul. Mocke nicht die Hook, die Kind-Row-Komponente, den Lade-Animator und drei Hilfsfunktionen, es sei denn, der Test benötigt tatsächlich Isolation an diesen Schnittstellen.
Verwenden Sie diese Regelsatz:
- Mocke externe Dienste: HTTP-Clients, Analysen, Browser-only-APIs, native Bridges
- Fiktive unstabile Plattform-APIs:
matchMedia, Timer, Electron-Vorladefunktionen, Capacitor-Plugins, wenn sie in jsdom nicht verfügbar sind - Vermeide das Mocking deiner eigenen Interna standardmäßig: Benutzerdefinierte Hooks, einfache Kinder, lokale Hilfsfunktionen
Ein Test, der aufgrund der Verwendung von Fakes für die schwierigen Teile durchläuft, hat nicht viel Vertrauen in die Releasefähigkeit gebracht.
Für Teams, die Beispiele und Muster rund um Runner-APIs benötigen, ist die Capgo Jest-Kategorie ein praktisches 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 aus einem der drei Fehler:
- Der Test behauptet zu früh.
- Der Test wartet mit willkürlichen Zeitschaltungen.
- The Komponente aktualisiert sich mehr als einmal, aber der Test modelliert nur eine Übergang.
Eine stabile asynchrone Testmethode 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 Timerverhalten und verwenden fiktive Timer.
Reacts Testumgebung erwartet auch, dass Sie die act() um Updates zu respektieren. Testing Library handhabt einen großen Teil davon für Sie, aber wenn Sie den Zustand manuell steuern oder Timer vorwärts schalten, müssen Sie sich immer noch über die Zeit des Flushens von Updates Gedanken machen.
Wissen Sie, welches Mocking-Tool Sie erreichen sollten
Verschiedene Mocking-Tools lösen unterschiedliche Probleme:
| Werkzeug | Beste Verwendung | Häufiger Fehler |
|---|---|---|
jest.fn() | Stehende Fake-Callbacks oder injizierte Funktionen | Verwendung zur Ersetzung eines ganzen Moduls, wenn ein einfacher Callback ausreicht |
jest.spyOn() | Beobachten oder überschreiben einer Methode auf einem realen Objekt oder Modul | Vergessen, die ursprüngliche Implementierung wiederherzustellen |
jest.mock() | Ersetzen einer Modul-Abhängigkeit an der Import-Grenze | Vordefiniertes Mocken großer Module und Verlust von bedeutender Funktionalität |
Beispiele helfen:
- Zurückgreifen auf
jest.fn()wenn ein Komponente einenonSubmitEigenschaften-Parameter annehmen. - Verwenden Sie
jest.spyOn()wenn Sie die Verifizierung einerconsole.error, einer Speichermethode oder eines exportierten API-Aufrufs benötigen. - Verwenden Sie
jest.mock()wenn der Import eines Moduls sonstweise auf I/O, native code, oder Verhalten außerhalb der Einheitsgrenze treffen würde.
Ein fortgeschrittener Bereich, den viele Anleitungen vernachlässigen, ist die Fehlerpfadprüfung in modernem React. Fehlergrenzen, verzögerte Zustandsänderungen und asynchrone Ersatz-UIs verdienen erste-Klasse-Tests, nicht nur das "glückliche Pfad"-Beispiel. Wenn ein Kind einen Fehler wirft, 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
Einige Teams verfolgen immer noch die Abdeckung wie es dasselbe wäre wie Vertrauen. Es ist nicht.
Sie können ein Abdeckungsziel erreichen und trotzdem die Regressionsfehler verpassen, die zählen.

Abdeckung ist ein Plan, nicht das Ziel
Abdeckungsberichte sind nützlich, wenn sie eine Frage beantworten: welche kritischen Pfade haben noch keine Schutz yet?
Sie sind nicht nützlich, wenn sie Entwickler dazu zwingen, trivialle Wrapper, statische Markup oder eine-Linien-Pass-through-Dateien zu testen, nur um einen Prozentsatz zu verbessern. Behandeln Sie die Abdeckung als ein Entdeckungstool. Wenn der Authentifizierungsstatus, die Abrechnungsaktionen, die Feature-Flags oder die Aktualisierungsanfragen keine Tests haben, ist das ein Signal. Wenn ein präsentatives Icon-Komponente keine Tests hat, ist das normalerweise nicht der Fall.
Ein gesunder Überprüfungsfrage ist einfach: reduziert diese Test die Auslieferungsrisiken?
- Ja: Es überprüft die Benutzersichtbarkeit auf einer kritischen Pfad.
- Vielleicht: Es schützt Geschäftslogik, die leicht während einer Refaktorisierung gebrochen werden kann.
- Nein: Es behauptet Implementierungsdetails oder dupliziert den Wert eines anderen Tests.
Was nicht getestet werden sollte
Viele React-Leitfäden geben immer noch nicht genug Zeit für die Omission auf. Diese Lücke ist wichtig, weil das Über-Mocken und die Implementierungs-Detail-Testung brüchige Suites erzeugen, die zwar bestehen, aber die Benutzererfahrung immer noch brechen, wie in der BrowserStack-Leitfaden zu "was nicht getestet werden sollte in React" beschrieben ist. Vermeiden oder stark einschränken Sie diese Muster:.
__CAPGO_KEEP_0__
- Internes Zustandsprüfungen: Testen Sie nicht direkt, wenn Sie prüfen können, ob das Panel geöffnet wurde.
isOpenFramework-Verhalten: - Testen Sie nicht, dass React einen Effekt aufgerufen hat. Testen Sie das Ergebnis dessen, was der Effekt ändert. Dritte Bibliotheksinhalte:
- Testen Sie Ihre Integration mit einem Datumsauswahl- oder Routen-Tool, nicht die eigene Darstellung der Bibliothek. Überbrochene Einheiten:
- Wenn Sie jedes Kind und jede Hilfsfunktion mockt haben, testen Sie möglicherweise nicht mehr bedeutendes Verhalten. Schlechte Tests sind schlimmer als fehlende Tests, wenn sie Refaktorisierungen blockieren und trotzdem keine Produktionsfehler erkennen.
Ein nützlicher Heuristik ist die Eigentümerschaft von Grenzen. Testen Sie, was Ihr __CAPGO_KEEP_0__ besitzt. Testen Sie nicht, was React, der Browser oder eine reife Bibliothek bereits besitzt, es sei denn, Ihre Integrationsschicht ändert den Vertrag.
A useful heuristic is boundary ownership. Test what your code owns. Don’t test what React, the browser, or a mature library already owns unless your integration layer changes the contract.
Wo Snapshots helfen und wo sie schaden
Snapshots sind nicht nutzlos. Sie werden nur leicht missbraucht.
Verwenden Sie sie sparsam für Komponenten mit stabilen, einfachen Ausgaben, bei denen eine breite strukturelle Differenz bedeutend ist. Vermeiden Sie sie für interaktive oder hochdynamische Komponenten, da sie Lärm erzeugen.
Bessere Alternativen existieren normalerweise:
- Falls Sie bedingte Anzeige verwenden, behaupten Sie die Präsenz oder Abwesenheit von Schlüsseltext.
- Falls Sie visuelle Zustandsänderungen verwenden, behaupten Sie die Rolle, Bezeichnung oder das Attribut, das zählt.
- Falls Sie Fehler und Fallbacks verwenden, behaupten Sie den tatsächlichen Fehlermeldung oder Warnbereich.
Wenn Ihr Team ein umfassenderes Qualitätssicherungsprozess außerhalb von Einheitstests benötigt, ist ein solides Begleiter ein Qualitätssicherungsprozess für Anwendungen der Tests, Release-Überprüfungen und Rollback-Planung als ein System behandelt. Das ist der geistige Wandel, der die Testqualität am schnellsten verbessert. Stellen Sie nicht mehr die Frage, wie viele Tests Sie haben. Beginnen Sie stattdessen mit der Frage, welche Fehler noch immer auf die Benutzer zukommen könnten.
Integrieren von Tests in eine Cross-Plattform CI/CD Pipeline
Eine Testsuite, die nur auf einem Entwickler-Notebook läuft, ist nur eine Empfehlung und keine Kontrolle.
Die Suite wird operativ, wenn jede Pull-Anfrage die gleichen Prüfungen in einem sauberen Umfeld ausführt und die Merges blockiert, wenn diese Prüfungen fehlschlagen. Das klingt offensichtlich, aber viele Teams lassen immer noch kritische Lücken bestehen. Tests werden manuell ausgeführt. Abdeckungsberichte sind optional. Verpackungs- und Release-Jobs beginnen, bevor die Test-Jobs abgeschlossen sind. Das ist, wie kleine UI-Regressionen in größere Release-Fehler schlüpfen können.

Ein Pull-Request sollte jeden Mal den gleichen Gate auslösen.
Für die Einheitstests von React sollte die CI ein paar Grundlagen haben:
- Jeder Pull-Request ausführen
- Abhängigkeiten aus Lockfile installieren
- Jedes Mal den gleichen Testbefehl verwenden
- Schnell auf Testfehler reagieren
- Nur nach erfolgreichem Testen Artefakte veröffentlichen
Dies ist der Kern der kontinuierlichen Bereitstellungspraktiken für App-TeamsVertrauen aufbauen, bevor man veröffentlicht und nicht danach.
Ein einfacher GitHub Actions-Workflow 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
This isn’t fancy, and that’s the point. The strongest pipelines are usually the least surprising ones.
Wieso ist das für Capacitor und Electron wichtiger
Cross-platform React-Anwendungen haben bei der Veröffentlichung mehr Risiken als Browser-Anwendungen, weil die gleiche Benutzeroberfläche code oft in verschiedenen Containern mit unterschiedlichen Laufzeitannahmen geliefert wird.
Eine paar Beispiele zeigen, wo Pipelines helfen:
- Capacitor-Anwendungen: Web code mag lokal funktionieren, aber scheitern, wenn ein Plugin-Brücke, Offline-Zustand oder ein App-Lifecycle-Randfall das Verhalten nach der Verpackung ändert.
- Elektron-Anwendungen: Eine Renderer-Komponente kann auf Präloader-APIs, Fenster-Messaging oder Desktop-only-Zustände angewiesen sein, die in einer reinen Browser-Testung nur dann existieren, wenn sie absichtlich nachgemacht werden.
- Gemeinsame Veröffentlichungs-Trainings: Ein schlechter Bundle kann mehrere Ziele beeinflussen, wenn Ihr Bereitstellungsprozess die Veröffentlichung nicht engmaschig überwacht.
Deshalb sollten Einheitstests vor Verpackungsaufgaben laufen und Verpackungsaufgaben sollten vor Verteilungsaufgaben laufen. Jeder Schritt reduziert das Risiko. Einheitstests fangen lokale Rückschritte schnell ein. Plattform-Verpackungen überprüfen Umgebungsannahmen. Manuelle Genehmigung oder stufenweise Veröffentlichung handhaben die letzte Veröffentlichungsvertraulichkeit.
Ein praktischer GitHub Actions-Workflow
Eine reifere Pipeline verteilt die Verantwortung normalerweise auf mehrere Aufgaben:
- Testaufgabe: Schnelle Einheit- und Hook-Tests
- Build-Aufgabe: Produktionsbuild nur nachdem die Tests erfolgreich waren
- Paket-Aufgabe: Capacitor Sync, Electron-Paketierung oder Artefaktbündelung
- Release-Aufgabe: Veröffentliche 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 ist. Eine Option in diesem Workflow ist Capgo, die signierte Web-Bundles für CapacitorJS- und Electron-Anwendungen mit Rollback-Unterstützung und kanalbasierten Ausrollen-Kontrollen veröffentlicht. In der Praxis bedeutet das, dass Ihre React-Testaufgabe als erste harte Schranke fungieren kann, bevor ein Web-Bundle in die Staging- oder Produktionslieferung kommt.
The Betriebsregel ist einfach. Lassen Sie die Release-Infrastruktur nicht für schwache Tests ausgleichen. Verwenden Sie die Release-Infrastruktur nachverlässlichen Tests, die bereits schlechte Änderungen ausgesiebt haben.
Eine zuverlässige Testanlage ändert das Verhalten des Teams. Ingenieure fusionieren mit weniger Hesitation. Rezensenten konzentrieren sich auf Randfälle anstatt grundlegende Basics manuell nachzurüsten. Release-Manager behandeln jeden Deploy nicht mehr wie ein Wettbewerb. Das ist das Ergebnis von gutem Unit-Testing für React.
Wenn Ihr Team React über Capacitor oder Electron ausliefern lässt, hängt die Release-Sicherheit von mehr als grünen lokalen Tests ab. Capgo Gibt Teams einen kontrollierten Weg, um signierte Web-Updates zu veröffentlichen, Zielrollout-Kanäle anzusteuern und schlechte Pakete ohne Wartezeit auf die Store-Überprüfung zurückzunehmen, was sich natürlich hinter einer CI-Pipeline einfügt, die bereits die Einhaltung von Unit-Tests vor der Bereitstellung erfordert.