In einer perfekten Welt Codebasis besteht keine Notwendigkeit, globale Objekte zu manipulieren, aber die Welt Codebasen sind chaotisch – und so testet.
Was Sie unbedingt vermeiden möchten, ist, dass sich ein Test auf den anderen auswirkt. Tests sollten unabhängig von ihrer Reihenfolge oder davon, ob einige Tests übersprungen werden, aussagekräftig sein.
Ein naiver Ansatz für Scheinwerte besteht darin, die Eigenschaften einfach auf den Wert zu setzen, den Sie in Ihrem Test benötigen.
Dies ist in Ordnung, solange Sie Werte in lokalen Objekten ändern, die diesem spezifischen Test gehören (erstellt wurden):
describe("override properties of local objects", () => { it("works and is harmless", () => { const myArray = [1]; myArray.length = 0; expect(myArray).toHaveLength(0); }); it("does not affect the next test", () => { const myArray = [1]; expect(myArray).toHaveLength(1); }); });
Wenn Sie das für globale Objekte tun, wird es chaotisch:
describe("don't override properties of global objects", () => { it("works before the property is overridden", () => { expect(window.innerWidth).toBeGreaterThan(0); }); it("works, but is evil", () => { window.innerWidth = 0; expect(window.innerWidth).toBe(0); }); it("fails in the test after the property was overridden", () => { expect(() => { expect(window.innerWidth).toBeGreaterThan(0); // <-- ERROR: expect(received).toBeGreaterThan(expected) }).toThrow(Error); }); });
Dafür wurde jest.replaceProperty() gemacht:
describe("use jest.replaceProperty() to override properties of global objects", () => { afterEach(() => { jest.restoreAllMocks(); }); it("works before the property is overridden", () => { expect(window.innerWidth).toBeGreaterThan(0); }); it("works and is harmless", () => { jest.replaceProperty(window, "innerWidth", 0); expect(window.innerWidth).toBe(0); }); it("does not affect the next test", () => { expect(window.innerWidth).toBeGreaterThan(0); }); });
Methoden können ähnlich wie Eigenschaften verspottet werden.
describe("override methods of local objects using jest.fn()", () => { it("works and is harmless", () => { const mySet = new Set([1]); mySet.has = jest.fn().mockReturnValue(false); expect(mySet.has(1)).toBeFalsy(); }); it("does not affect the next test", () => { const mySet = new Set([1]); expect(mySet.has(1)).toBeTruthy(); }); });
Wenn Sie myObject.someFunction = jest.fn() für globale Objekte verwenden, hängen Ihre Tests möglicherweise voneinander ab und verlieren ihre Bedeutung:
describe("don't override methods of global objects using jest.fn()", () => { it("works before the method is overridden", () => { expect(document.getElementById("foo")).toBeNull(); }); it("works, but is evil", () => { const el = document.createElement("div"); document.getElementById = jest.fn().mockReturnValue(el); expect(document.getElementById("foo")).toBe(el); }); it("fails in the test after the property was overridden", () => { expect(() => { expect(document.getElementById("foo")).toBeNull(); // <-- ERROR: expect(received).toBeNull() }).toThrow(Error); }); });
Wie sollen wir Methoden in globalen Objekten verspotten? Dafür ist jest.spyOn() gut:
describe("use jest.spyOn() to override methods of global objects", () => { afterEach(() => { jest.restoreAllMocks(); }); it("works before the method is overridden", () => { expect(document.getElementById("foo")).toBeNull(); }); it("works and is harmless", () => { const el = document.createElement("div"); jest.spyOn(document, "getElementById").mockReturnValue(el); expect(document.getElementById("foo")).toBe(el); }); it("does not affect the next test", () => { expect(document.getElementById("foo")).toBeNull(); }); });
Wenn Sie sicher sein möchten, dass sich das System bei allen Tests im gleichen (frischen, sauberen) Zustand befindet, müssen Sie den Mock-Zustand nach jedem Test wiederherstellen.
Die einfachste Lösung besteht darin, die Konfigurationseigenschaft „restoreMocks“ festzulegen.
Die einfachste Option besteht darin, jest.restoreAllMocks() in afterEach() aufzurufen
Manchmal möchten Sie Dinge für alle Tests in einer Datei verspotten. Wenn Sie jest.spyOn() und jest.replaceProperty() auf der obersten Ebene oder in einem beschreiben()-Block verwenden, werden alle Mocks zurückgesetzt, nachdem der erste Test ausgeführt wurde.
Auf der obersten Ebene können Sie Eigenschaften und Methoden sicher überschreiben, ohne jest.spyOn() und jest.replaceProperty().
Wenn Sie Dinge nur für einen beschreiben()-Block verspotten möchten, müssen Sie diese Aufrufe in einem beforeEach()-Hook durchführen.
Das obige ist der detaillierte Inhalt vonScherz-Rekapitulation: Eigenschaften und Methoden globaler Objekte sicher simulieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!