代码之家  ›  专栏  ›  技术社区  ›  dwjohnston

jest如何允许模块的变异?

  •  7
  • dwjohnston  · 技术社区  · 7 年前

    我在这里问的这个问题:

    Why does mutating a module update the reference if calling that module from another module, but not if calling from itself?

    然而,事实证明,ES6模块实际上是不能变异的——它们的所有属性都被视为常量。( See this answer )

    这是怎么发生的?

    我想象它是一个正在运行的babel插件——将模块传输到CommonJS模块?有关于这方面的文件吗?

    有没有办法查看传输的代码?

    1 回复  |  直到 7 年前
        1
  •  6
  •   Community Mohan Dere    6 年前

    ES6模块实际上不能变异——它们的所有属性都被视为常量。

    有趣的你说得对,即使是这么简单的事情:

    import * as lib from "./lib";  // import an ES6 module
    const spy = jest.spyOn(lib, 'someFunc');  // spy on someFunc
    

    jest.spyOn replaces the method on the object with a spy 和 lib.someFunc someFunc 在ES6模块中。


    但不知何故,当Jest测试模块时,它们可能会发生变异,这就是Jest允许模拟的方式。

    这是怎么发生的?

    它们只能变异,因为 Jest

    可以 能跑吗 使用实际的ES6模块 Node experimental support for ES6 Modules 但我没有试过)。


    我想这是一个正在运行的babel插件-传输模块…有关于这个的文档吗?

    " babel-jest is automatically installed when installing Jest and will automatically transform files if a babel configuration exists in your project. To avoid this behavior, you can explicitly reset the transform configuration option"

    所以默认情况下 开玩笑 它使用 babel (还有其他一些事情,比如 hoisting calls to jest.mock ).

    开玩笑 transform 它将“正则表达式映射到变压器的路径”。


    对转换是在中完成的 jest-runtime here here .

    查看传输代码的最简单方法是查看缓存。

    你可以通过跑步来做到这一点 开玩笑 --showConfig 选项,该选项将输出 config 运行时使用 开玩笑 . 通过查看“cacheDirectory”的值可以找到缓存位置。

    然后跑 开玩笑 和 --clearCache

    最后,跑 开玩笑


    实例

    最新的

    // lib.js
    export const someFunc = () => 1;
    
    
    // code.js
    import { someFunc } from './lib';
    export const func = () => someFunc() + 1;
    
    
    // code.test.js
    import { func } from './code';
    import * as lib from './lib';
    
    test('func', () => {
      const spy = jest.spyOn(lib, 'someFunc');
      func();
      expect(spy).toHaveBeenCalled();  // SUCCESS
    });
    

    ……为此:

    // lib.js
    "use strict";
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports.someFunc = void 0;
    const someFunc = () => 1;
    exports.someFunc = someFunc;
    
    
    // code.js
    "use strict";
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports.func = void 0;
    var _lib = require("./lib");
    const func = () => (0, _lib.someFunc)() + 1;
    exports.func = func;
    
    
    // code.test.js
    "use strict";
    var _code = require("./code");
    var lib = _interopRequireWildcard(require("./lib"));
    function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
    test('func', () => {
      const spy = jest.spyOn(lib, 'someFunc');
      (0, _code.func)();
      expect(spy).toHaveBeenCalled(); // SUCCESS
    });
    

    这个 import * as lib from 'lib'; 行由 _interopRequireWildcard require

    每一个电话 "will get exactly the same object returned, if it would resolve to the same file" 所以 code.js code.test.js require('./lib') .

    someFunc 输出为 exports.someFunc 这使得它可以被重新分配。


    巴别塔 进入