Heim  >  Artikel  >  Web-Frontend  >  Scherz-Rekapitulation: Eigenschaften und Methoden globaler Objekte sicher simulieren

Scherz-Rekapitulation: Eigenschaften und Methoden globaler Objekte sicher simulieren

WBOY
WBOYOriginal
2024-07-19 15:10:32305Durchsuche

Jest Recap: Safely Mock Properties and Methods of Global Objects

TL;DR:

  • Sie möchten vermeiden, dass überschriebene/verspottete Eigenschaften/Methoden andere Tests beeinflussen.
  • Für lokale Objekte (die von diesem Test erstellt wurden und ihm gehören) können (und sollten) Sie verwenden
    • localObject.theAnswer = 42 und
    • localObject.calcTheAnswer = jest.fn(() => 42).
  • Für globale Objekte sollten Sie verwenden
    • jest.replaceProperty(globalObject, "theAnswer", 42) und
    • jest.spyOn(globalObject, "calcTheAnswer").mockReturnValue(42).
  • Stellen Sie sicher, dass jest.restoreAllMocks() in einem afterEach()-Hook aufgerufen wird.

Was?

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.

Spotteigenschaften

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);
    });
});

Spottmethoden

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();
    });
});

Sie müssen aufräumen

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

So verspotten Sie etwas für alle Tests

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Karte in JSNächster Artikel:Karte in JS