在jest docs中,我找到了测试反应组件的简单示例:
// Link.react.test.js
import React from 'react';
import Link from '../Link.react';
import renderer from 'react-test-renderer';
test('Link changes the class when hovered', () => {
const component = renderer.create(
<Link page="http://www.facebook.com">Facebook</Link>,
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
// manually trigger the callback
tree.props.onMouseEnter();
// re-rendering
tree = component.toJSON();
expect(tree).toMatchSnapshot();
// manually trigger the callback
tree.props.onMouseLeave();
// re-rendering
tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
为什么我们必须导入React
和react-test-renderer
,但不必导入其他特定于测试的内容,例如test
,expect
?
有人可以解释,这是如何工作的,以及测试运行时实际发生的事情?
答案 0 :(得分:1)
它找到二进制文件 jest
并用你的脚本执行它,这个二进制文件会首先编译你的代码然后运行它,所以那些用于测试的模块将在编译时找到那些函数关键字时导入。您将Jest安装到原始应用程序以测试组件。 React
模块或其他它真的是你的东西。
<强>更新强>
通过跟踪Jest的存储库
jest/packages/jest-runtime/src/script_transformer.js,我们发现它利用Node.js模块VM来运行脚本,它有一些方法,如vm.createContext()
和vm.Script().runInContext()
,所以那些内部模块应该是以编程方式导入到沙箱。
来自VM
的示例const vm = require('vm');
const sandbox = { globalVar: 1 }; // <=> import expect, test
vm.createContext(sandbox);
...
vm.runInContext('globalVar *= 2;', sandbox); // <=> Our test code.
因此,expect
和test
等模块可能会像上面vm.createContext()
那样导入。
很难确切知道如何在短时间内完成这项工作,但我们仍然可以获得一些线索:
jest/packages/jest-runtime/src/cli/index.js 中的
...
import Runtime from '../'; // ---> jest/packages/jest-runtime/src/index.js
export function run(...) {
...
Runtime.createContext(
...
).then(
const runtime = new Runtime(config, environment, hasteMap.resolver);
runtime.requireModule(filePath);
...
)
}
Runtime
是
jest/packages/jest-runtime/src/index.js
...
import Resolver from 'jest-resolve';
...
import ScriptTransformer from './script_transformer';
...
requireModule() {
_execModule(...)
}
...
_execModule() {
...
this._createRequireImplementation(
...
this._createJestObjectFor(...)
}
这里有许多关键工作,需要模块,检测环境配置,有Resolver
来查找模块ID,检测模块的类型,应该模拟,返回jestObject
,全部包装到我们的沙箱进行测试。
这是执行mock
的核心