【问题标题】:Testing React Components: How does it work?测试 React 组件:它是如何工作的?
【发布时间】:2018-09-13 19:21:40
【问题描述】:

在 jest 文档中,我发现了这个测试反应组件的简单示例:

// 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

有人可以解释一下,这是如何在幕后工作的以及运行测试时实际发生的情况吗?

【问题讨论】:

标签: javascript reactjs jestjs


【解决方案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

【讨论】:

    猜你喜欢
    • 2014-07-14
    • 2015-08-09
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    相关资源
    最近更新 更多