Moki - nicht beißen!
Sie sollen Ihnen helfen, einfachere und zuverlässigere Tests zu erstellen. In dieser Artikelserie zeige ich Ihnen die Muster, auf die ich mich beim Verspotten (oder „Stubben“) von React-Komponenten stütze.
Hier ist ein gutes Beispiel für einen Komponentenstub. Ich benutze
jest.mock, worauf wir weiter unten näher eingehen werden.
jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(() => (
<div data-testid="PostContent" />
))
}))
Ein typischer React-Komponentenstub sollte nicht komplizierter aussehen. Beachten Sie den sehr einfachen Stub-Wert (
div) und ein Attribut data-testid, mit dem wir eine gerenderte Instanz im DOM sehr leicht finden können. Konventionell muss die verwendete Testkennung mit dem Komponentennamen übereinstimmen. In diesem Fall ist es PostContent.
Bevor wir uns ansehen, wie sie verwendet werden, werfen wir zunächst einen Blick darauf, was Mocks sind und warum Sie sie möglicherweise sogar verwenden möchten.
Was ist ein Mock?
In der JavaScript-Welt wird der Begriff Mock sehr häufig verwendet, um sich auf verspottete Implementierungen oder Testdoppel zu beziehen . Verspottete Implementierungen sind einfach Werte, die andere in Ihrem Produktionscode ersetzen, während Ihre Tests ausgeführt werden. Sie probieren die Schnittstelle des zu ersetzenden Objekts aus, sodass der Rest Ihres Codes so funktioniert, als gäbe es keinen Ersatz.
Es gibt verschiedene Gründe, warum Sie dies tun möchten. Wir werden sie mit Beispielen betrachten.
Wenn Sie mehr über verspottete Implementierungen erfahren möchten, lesen Sie Martin Fowlers Buch Mocks Are Not Stubs .
Scherz und Spott
Jest verfügt über eine Funktion
jest.mock, mit der Sie ganze Module verspotten können, die Sie ersetzen. In diesem Tutorial habe ich mich auf diese Funktion konzentriert, obwohl es andere Möglichkeiten gibt, Objekte in JavaScript zu ersetzen.
In dem Buch Mastering React Test-Driven Development verwende ich ES6 -Modulimporte, um Testdoppel zu erstellen. Dieser Ansatz bietet etwas mehr Flexibilität, sieht aber etwas hackiger aus.
Jest jest.mockEs heißt, Mocks stellen sicher, dass Ihre Tests schnell und nicht spröde sind .
Dies ist zwar wahr, aber nicht der Hauptgrund, warum ich Mocks benutze.
Ich benutze Mocks, weil sie mir helfen, meine Tests unabhängig voneinander zu halten.
Um zu verstehen, warum dies der Fall ist, schauen wir uns ein Beispiel an.
Warum Moki?
Unten finden Sie eine Liste einer Komponente
BlogPage, die zwei Dinge ausführt: Sie ruft idvon einer Eigenschaft ab urlund zeigt dann eine PostContentKomponente damit an id.
const getPostIdFromUrl = url =>
url.substr(url.lastIndexOf("/") + 1)
export const BlogPage = ({ url }) => {
const id = getPostIdFromUrl(url)
return (
<PostContent id={id} />
)
}
Stellen Sie sich vor, Sie schreiben Tests für diese Komponente und alle Ihre Tests sind in
BlogPage.test.jseiner einzigen Testsuite enthalten, die Komponenten BlogPageund abdeckt PostContent.
Zu diesem Zeitpunkt benötigen Sie die Mocks noch nicht: Wir haben
PostContentsie noch nicht gesehen , aber angesichts der Größe BlogPagesind zwei separate Testsuiten nicht erforderlich, da BlogPagedies im Allgemeinen einfach ist PostContent.
Stellen Sie sich nun vor, Sie fügen
BlogPagey und y PostContentFunktionen hinzu. Als begabter Entwickler fügen Sie jeden Tag mehr und mehr Funktionen hinzu.
Es wird schwieriger, die Tests funktionsfähig zu halten. Jeder neue Test ist komplexer aufgebaut, und die Testsuite nimmt mehr Zeit in Anspruch - eine Belastung, die jetzt unterstützt werden muss.
Dies ist ein häufiges Problem, und ich sehe es ständig in React-Codebasen. Testsuiten, in denen selbst die kleinste Änderung dazu führt, dass viele Tests fehlschlagen.
Eine Lösung besteht darin, Testsuiten aufzuteilen. Wir werden gehen
BlogPage.test.jsund eine neue erstellen PostContent.test.js, die Tests ausschließlich für enthalten sollte PostContent. Die Grundidee ist , dass alle Funktionen in platziert PostContentsein muss in PostContent.test.jsund alle Funktionen in platziert BlogPage(wie etwa URL - Parsing) in sein muss BlogPage.test.js.
Okay.
Aber was ist, wenn gerendert wird?
PostContent hat Nebenwirkungen?
export const PostContent = ({ id }) => {
const [ text, setText ] = useState("")
useEffect(() => {
fetchPostContent(id)
}, [id])
const fetchPostContent = async () => {
const result = await fetch(`/post?id=${id}`)
if (result.ok) {
setText(await result.text())
}
}
return <p>{text}</p>
};
Die Testsuite
BlogPage.test.jsmuss sich der Nebenwirkungen bewusst sein und darauf vorbereitet sein, damit umzugehen. Zum Beispiel muss er eine fetchAntwort bereithalten .
Die Abhängigkeit, die wir durch die Aufteilung unserer Testsuiten vermeiden wollten, besteht weiterhin.
Die Organisation unserer Tests ist sicherlich besser geworden, aber am Ende hat nichts unsere Tests weniger zerbrechlich gemacht.
Dafür brauchen wir einen Stummel (oder Mock)
PostContent.
Und im nächsten Teil werden wir uns ansehen, wie das geht.
Ist es wirklich notwendig?
Übrigens ein paar Worte zum Übergang von End-to-End-Tests zu Unit-Tests.
Testdoppel sind ein Schlüsselindikator dafür, dass Sie Komponententests schreiben.
Viele erfahrene Tester starten neue Projekte sofort mit Unit-Tests (und Verspottungen), da sie wissen, dass sie mit zunehmender Codebasis auf Probleme mit der Testinstabilität stoßen werden.
Unit-Tests sind normalerweise viel kleiner als End-to-End-Tests. Sie können so klein sein, dass sie oft nicht mehr als drei oder vier Codezeilen benötigen. Dies macht sie zu großartigen Kandidaten für Social-Coding-Praktiken wie Paar- und Ensemble-Programmierung.
Selbst wenn wir Unit-Tests durchführen, sind Test-Doubles nicht immer erforderlich - sie sind nur ein weiteres Tool in Ihrer Suite, das Sie wissen müssen, wann und wie Sie es anwenden müssen.
Im nächsten Teil werden wir die grundlegenden Verspottungstechniken behandeln .
