我如何使用Jest模拟ES6模块导入?
我如何使用Jest模拟ES6模块导入?
我想测试我的一个ES6模块是否以特定方式调用另一个ES6模块。使用Jasmine非常容易 -
应用程序代码:
// myModule.js import dependency from './dependency'; export default (x) => { dependency.doSomething(x * 2); }
测试代码:
//myModule-test.js import myModule from '../myModule'; import dependency from '../dependency'; describe('myModule', () => { it('calls the dependency with double the input', () => { spyOn(dependency, 'doSomething'); myModule(2); expect(dependency.doSomething).toHaveBeenCalledWith(4); }); });
Jest的等效物是什么?我觉得这是一个非常简单的想法,但我一直在试图弄清楚它而感到非常困惑。
我接近的方法是用require代替import,并将它们移动到测试/函数内部。这两件事我都不想做。
// myModule.js export default (x) => { const dependency = require('./dependency'); // Yuck dependency.doSomething(x * 2); } //myModule-test.js describe('myModule', () => { it('calls the dependency with double the input', () => { jest.mock('../dependency'); myModule(2); const dependency = require('../dependency'); // Also yuck expect(dependency.doSomething).toBeCalledWith(4); }); });
如果函数在dependency.js内是默认导出,我想获得额外的积分。然而,我知道在Jasmine中不能正确跟踪默认导出(或者至少我从没成功过),所以我不抱希望在Jest中也能实现。
admin 更改状态以发布 2023年5月21日
你必须自己模拟模块并设置间谍:
import myModule from '../myModule'; import dependency from '../dependency'; jest.mock('../dependency', () => ({ doSomething: jest.fn() })) describe('myModule', () => { it('calls the dependency with double the input', () => { myModule(2); expect(dependency.doSomething).toBeCalledWith(4); }); });
编辑:已经过了几年,这不再是正确的做法了(可能从一开始就不是,我的错)。
对导入的模块进行变异是不好的,可能会导致测试的通过或失败取决于执行顺序等副作用。
为了历史目的,我将保留此答案的原始形式,但你应该真正使用jest.spyOn
或jest.mock
。请参阅jest文档或本页面的其他答案以获取详细信息。
以下是原始答案:
我已经用一个涉及import *
的黑客方式来解决这个问题。 它甚至适用于命名和默认导出!
对于命名导出:
// dependency.js export const doSomething = (y) => console.log(y)
// myModule.js import { doSomething } from './dependency'; export default (x) => { doSomething(x * 2); }
// myModule-test.js import myModule from '../myModule'; import * as dependency from '../dependency'; describe('myModule', () => { it('calls the dependency with double the input', () => { dependency.doSomething = jest.fn(); // Mutate the named export myModule(2); expect(dependency.doSomething).toBeCalledWith(4); }); });
对于默认导出:
// dependency.js export default (y) => console.log(y)
// myModule.js import dependency from './dependency'; // Note lack of curlies export default (x) => { dependency(x * 2); }
// myModule-test.js import myModule from '../myModule'; import * as dependency from '../dependency'; describe('myModule', () => { it('calls the dependency with double the input', () => { dependency.default = jest.fn(); // Mutate the default export myModule(2); expect(dependency.default).toBeCalledWith(4); // Assert against the default }); });