测试React组件:它是如何工作的?

时间:2018-04-04 09:31:24

标签: javascript reactjs jest

在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();
});

为什么我们必须导入Reactreact-test-renderer,但不必导入其他特定于测试的内容,例如testexpect

有人可以解释,这是如何工作的,以及测试运行时实际发生的事情?

1 个答案:

答案 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.

因此,expecttest等模块可能会像上面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

的核心