完璧な世界 コードベースではグローバルオブジェクトを操作する必要はありませんが、世界 コードベースは乱雑です - そしてテスト中です。
何としても避けたいのは、一方のテストが他方のテストに影響を与えることです。テストは、順序や一部のテストがスキップされたかどうかに関係なく、意味のあるものである必要があります。
モック値への素朴なアプローチは、プロパティをテストで必要な値に設定することです。
この特定のテストが所有する (作成した) ローカル オブジェクトの値を変更する限り、これは問題ありません:
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 サイトの他の関連記事を参照してください。