使用 Jest 模擬同一模組中的函數
在同一模組中模擬函數時,了解 Jest預設模擬的限制至關重要
問題:
匯入模組並直接模擬其匯出的函數(如下例所示)可能會導致意外行為。
// module.js export function bar() { return 'bar'; } export function foo() { return `I am foo. bar is ${bar()}`; } // module.test.js import * as module from '../src/module'; describe('module', () => { let barSpy; beforeEach(() => { barSpy = jest.spyOn(module, 'bar').mockImplementation(jest.fn()); }); it('foo', () => { module.bar.mockReturnValue('fake bar'); expect(module.foo()).toEqual('I am foo. bar is fake bar'); // Fails: Expected "I am foo. bar is fake bar" but received "I am foo. bar is bar" }); });
說明:
以上例如, foo 在匯入期間直接呼叫原始 bar 函數。即使 barSpy 在測試設定期間正確更新,foo 仍然引用未模擬的 bar 函數,導致輸出不正確。
解決方案1:
導入模組進入自己的程式碼檔案:
要避免此問題,模組可以匯入到自己的程式碼檔案中,確保所有匯出的實體都是從同一個實例匯入的。
// module.js export function bar() { return 'bar'; } export function foo() { return `I am foo. bar is ${thisModule.bar()}`; } // module.test.js import * as module from './module'; describe('module', () => { it('foo', () => { spyOn(module, 'bar').and.returnValue('fake bar'); expect(module.foo()).toEqual('I am foo. bar is fake bar'); }); });
在此修改後的範例中,foo 現在透過匯入的實例 module.bar 存取 bar,因此可以輕鬆進行模擬。
解決方案2:
手動模擬導入:
或者,可以在測試設定中手動模擬導入,建立與未模擬版本隔離的模組的新實例。
// module.test.js jest.mock('../src/module'); const * as mockedModule = require('../src/module'); describe('module', () => { beforeEach(() => { mockedModule.bar.mockImplementation(jest.fn()); }); it('foo', () => { mockedModule.bar.mockReturnValue('fake bar'); expect(mockedModule.foo()).toEqual('I am foo. bar is fake bar'); }); });
在此方法中,使用模擬實例mockedModule進行測試,防止來自未模擬導入的干擾。
以上是如何使用 Jest 有效模擬同一模組內的函數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!