【问题标题】:How can I mock ES6 imported modules if they are read-only?如果它们是只读的,我如何模拟 ES6 导入的模块?
【发布时间】:2017-05-16 21:47:55
【问题描述】:

由于导入 ES6 模块会为您提供该模块的只读视图,因此模拟它会产生错误 'x' is read-only。这使我无法通过破坏其依赖关系来隔离被测代码。我不确定如何解决这个问题。

http://exploringjs.com/es6/ch_modules.html

*我会抛出一个 Plunker,但我无法让它识别 import 语句,而且 JSFiddle 似乎不允许其他文件,这些文件本来是用于导出模块的。

【问题讨论】:

标签: 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 的对象,避免导入单个属性。

    【讨论】:

      猜你喜欢
      • 2016-05-16
      • 2021-01-21
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 2016-10-25
      • 1970-01-01
      相关资源
      最近更新 更多