【问题标题】:How can I mock ES6 imported modules if they are read-only?如果它们是只读的,我如何模拟 ES6 导入的模块?
【发布时间】:2017-05-16 21:47:55
【问题描述】:
【问题讨论】:
标签:
javascript
unit-testing
import
ecmascript-6
【解决方案1】:
如果您正在使用 sinon,我的建议是停止使用它。他们不支持模拟只读模块并且对该主题非常激进
https://github.com/sinonjs/sinon/issues/1711
另一方面,通过 jest,您可以轻松地模拟 ES6 只读模块,如下所示:
const myMockedModule = {
...jest.requireActual('my-es6-readonly-module'),
theFunctionIWantToMock: jest.fn(),
}
jest.mock('my-es6-readonly-module', () => myMockedModule);
您需要将其作为规范的第一行。使用这种方法,您可以模拟从任何模块直接导出的任何项目,即使它是只读的,因为 jest 会拦截 require 方法。
这对于 mocha 也不是很实用,因为 mocha 在同一进程中加载所有测试,而其他一些测试套件可能会直接或间接加载您要模拟的模块,它会搞砸您的测试. Jest 是要走的路,因为它在一个单独的过程中加载每个规范,使一个规范不会干扰另一个规范,因此这种模拟方法变得可行。
【解决方案2】:
我的解决方案是改变我的导出方式。如果我导出一个属性对象,而不是单个属性本身,我不会收到错误消息。这似乎是因为 Object.freeze 只有一层深,所以导出的对象是冻结的,而不是子对象。
import {ua} from './index';
./index.js 导出一个命名对象,其中包含我要覆盖的道具:
export const ua = {
deleteUser,
loadUsers
};
这在我的测试代码中允许以下内容:
ua.loadUsers = function () {
expect(delUspy.calledOnce).toBe(true);
expect(loadUspy.callCount).toEqual(1);
done();
};
...但是ua = {} 失败了,因为它被冻结了。
那么答案就是导出 props 的对象,避免导入单个属性。