ホームページ >ウェブフロントエンド >jsチュートリアル >Jest の要約: グローバル オブジェクトのプロパティとメソッドを安全にモックする

Jest の要約: グローバル オブジェクトのプロパティとメソッドを安全にモックする

WBOY
WBOYオリジナル
2024-07-19 15:10:32344ブラウズ

Jest Recap: Safely Mock Properties and Methods of Global Objects

TL;DR:

  • オーバーライド/モックされたプロパティ/メソッドが他のテストに影響を与えることを避けたいと考えています。
  • ローカル オブジェクト (このテストによって作成および所有される) の場合は、使用できます (使用する必要があります)。
    • localObject.theAnswer = 42 および
    • localObject.calcTheAnswer = jest.fn(() => 42).
  • グローバルオブジェクトには使用する必要があります
    • jest.replaceProperty(globalObject, "theAnswer", 42) および
    • jest.spyOn(globalObject, "calcTheAnswer").mockReturnValue(42).
  • jest.restoreAllMocks() が afterEach() フックで呼び出されていることを確認してください。

何?

完璧な世界 コードベースではグローバルオブジェクトを操作する必要はありませんが、世界 コードベースは乱雑です - そしてテスト中です。

何としても避けたいのは、一方のテストが他方のテストに影響を与えることです。テストは、順序や一部のテストがスキップされたかどうかに関係なく、意味のあるものである必要があります。

プロパティのモック化

モック値への素朴なアプローチは、プロパティをテストで必要な値に設定することです。
この特定のテストが所有する (作成した) ローカル オブジェクトの値を変更する限り、これは問題ありません:

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

グローバル オブジェクトに対してこれを行うと、面倒になります:

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

これは jest.replaceProperty() が作成された目的です:

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

モックメソッド

メソッドはプロパティと同様にモック化できます。

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

グローバル オブジェクトに対して myObject.someFunction = jest.fn() を使用すると、テストが相互に依存し、その意味が失われる可能性があります。

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

グローバル オブジェクトのメソッドをどのようにモックすればよいでしょうか?これが jest.spyOn() の利点です:

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

掃除しなければなりません

すべてのテストでシステムが同じ (新鮮でクリーンな) 状態であることを確認したい場合は、各テストの後にモックの状態を復元する必要があります。

最も簡単な解決策は、restoreMocks 構成プロパティを設定することです。

最も簡単なオプションは、afterEach() で jest.restoreAllMocks() を呼び出すことです

すべてのテストで何かをモックする方法

ファイル内のすべてのテストについてモックを作成したい場合があります。 jest.spyOn() と jest.replaceProperty() をトップレベルまたは description() ブロックで使用すると、最初のテストの実行後にすべてのモックがリセットされます。

トップレベルでは、jest.spyOn() や jest.replaceProperty() を使用せずに、プロパティとメソッドを安全にオーバーライドできます。

describe() ブロックのみをモックしたい場合は、beforeEach() フックでこれらの呼び出しを行う必要があります。

以上がJest の要約: グローバル オブジェクトのプロパティとメソッドを安全にモックするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:JS でのマップ次の記事:JS でのマップ