玩笑如何允许模块突变?
How does jest allow mutation of modules?
我在这里问的这个问题:
我问的是模块突变的性质。
然而事实证明,ES6 模块实际上不能改变——它们的所有属性都被视为常量。 ()
但不知何故——当 Jest 测试模块时——它们可以被改变,这就是 Jest 允许模拟的方式。
这是怎么回事?
我想这是一个 babel 插件 运行 - 将模块转译为 CommonJS 模块?有没有关于这个的文档?
有没有办法查看转译后的代码?
ES6 modules can't actually be mutated - all of their properties are treated as constants.
有意思。你是对的,即使是这么简单的事情:
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
应该绑定到 ES6 模块中的 someFunc
。
But somehow - when Jest tests modules - they can be mutated, and that's how Jest allows for mocking.
How is this happening?
它们只能被改变,因为 Jest
实际上并没有使用 ES6 模块。
(为了完整起见,我想 可能 可以 运行 Jest
通过使用 Node
的 experimental support for ES6 Modules 但我没试过)。
I imagine that it's a babel plugin that that's running - transpiling the module...Is there any documentation about this?
所以默认情况下 Jest
将使用 babel-jest
,它使用 babel
转译源代码(并做一些其他事情,例如 hoisting calls to jest.mock
)。
请注意,Jest
也可以使用 transform
进行配置,它将“正则表达式映射到转换器的路径”。
Is there a way to view the transpiled code?
是的。转换在 jest-runtime
here and the output is saved to a cache here.
中完成
查看转译代码的最简单方法是查看缓存。
你可以通过 运行ning Jest
和 --showConfig
选项来做到这一点,它将输出 运行ning [=16= 时使用的 config
].可以通过查看“cacheDirectory”的值找到缓存位置。
然后 运行 Jest
使用 --clearCache
选项清除缓存。
最后,运行 Jest
通常缓存目录将包含您项目的转译代码。
例子
最新的 Jest
(v24) 将转译此代码:
// 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
。
每次调用 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
,允许重新分配。
所以是的,你完全正确。像这样的间谍(或嘲笑)之所以有效,是因为 ES6 模块被 babel
转译为 Node
模块,其方式允许它们发生变异。
我在这里问的这个问题:
我问的是模块突变的性质。
然而事实证明,ES6 模块实际上不能改变——它们的所有属性都被视为常量。 (
但不知何故——当 Jest 测试模块时——它们可以被改变,这就是 Jest 允许模拟的方式。
这是怎么回事?
我想这是一个 babel 插件 运行 - 将模块转译为 CommonJS 模块?有没有关于这个的文档?
有没有办法查看转译后的代码?
ES6 modules can't actually be mutated - all of their properties are treated as constants.
有意思。你是对的,即使是这么简单的事情:
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
应该绑定到 ES6 模块中的 someFunc
。
But somehow - when Jest tests modules - they can be mutated, and that's how Jest allows for mocking.
How is this happening?
它们只能被改变,因为 Jest
实际上并没有使用 ES6 模块。
(为了完整起见,我想 可能 可以 运行 Jest
通过使用 Node
的 experimental support for ES6 Modules 但我没试过)。
I imagine that it's a babel plugin that that's running - transpiling the module...Is there any documentation about this?
所以默认情况下 Jest
将使用 babel-jest
,它使用 babel
转译源代码(并做一些其他事情,例如 hoisting calls to jest.mock
)。
请注意,Jest
也可以使用 transform
进行配置,它将“正则表达式映射到转换器的路径”。
Is there a way to view the transpiled code?
是的。转换在 jest-runtime
here and the output is saved to a cache here.
查看转译代码的最简单方法是查看缓存。
你可以通过 运行ning Jest
和 --showConfig
选项来做到这一点,它将输出 运行ning [=16= 时使用的 config
].可以通过查看“cacheDirectory”的值找到缓存位置。
然后 运行 Jest
使用 --clearCache
选项清除缓存。
最后,运行 Jest
通常缓存目录将包含您项目的转译代码。
例子
最新的 Jest
(v24) 将转译此代码:
// 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
。
每次调用 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
,允许重新分配。
所以是的,你完全正确。像这样的间谍(或嘲笑)之所以有效,是因为 ES6 模块被 babel
转译为 Node
模块,其方式允许它们发生变异。