如果你是 React 新手,我们建议使用 。 It is ready to use and ships with Jest! 您只需要添加 来渲染快照。

    运行

    如果你已经有一个应用,你仅需要安装一些包来使他们运行起来。 我们使用babel-jest包和babel-preset-react,从而在测试环境中转换我们代码。 可参考

    运行

    1. yarn add --dev jest babel-jest babel-preset-env babel-preset-react react-test-renderer

    你的package.json文件应该像下面这样(<current-version>是当前包的最新版本号) 请添加脚本项目和 jest 配置:

    1. // package.json
    2. "dependencies": {
    3. "react": "<current-version>",
    4. "react-dom": "<current-version>"
    5. },
    6. "devDependencies": {
    7. "babel-jest": "<current-version>",
    8. "babel-preset-env": "<current-version>",
    9. "babel-preset-react": "<current-version>",
    10. "jest": "<current-version>",
    11. "react-test-renderer": "<current-version>"
    12. },
    13. "scripts": {
    14. "test": "jest"
    15. }
    1. // .babelrc
    2. {
    3. "presets": ["env", "react"]
    4. }

    准备工作已经完成!

    让我们来为一个渲染超链接的 Link 组件创建快照测试

    现在,使用React的test renderer和Jest的快照特性来和组件交互,获得渲染结果和生成快照文件:

    1. // Link.react.test.js
    2. import React from 'react';
    3. import Link from '../Link.react';
    4. import renderer from 'react-test-renderer';
    5. test('Link changes the class when hovered', () => {
    6. const component = renderer.create(
    7. <Link page="http://www.facebook.com">Facebook</Link>,
    8. );
    9. let tree = component.toJSON();
    10. expect(tree).toMatchSnapshot();
    11. // manually trigger the callback
    12. tree.props.onMouseEnter();
    13. // re-rendering
    14. tree = component.toJSON();
    15. expect(tree).toMatchSnapshot();
    16. // manually trigger the callback
    17. tree.props.onMouseLeave();
    18. // re-rendering
    19. tree = component.toJSON();
    20. expect(tree).toMatchSnapshot();
    1. exports[`Link changes the class when hovered 1`] = `
    2. <a
    3. className="normal"
    4. href="http://www.facebook.com"
    5. onMouseEnter={[Function]}
    6. onMouseLeave={[Function]}>
    7. Facebook
    8. </a>
    9. `;
    10. exports[`Link changes the class when hovered 2`] = `
    11. <a
    12. className="hovered"
    13. href="http://www.facebook.com"
    14. onMouseEnter={[Function]}
    15. onMouseLeave={[Function]}>
    16. Facebook
    17. </a>
    18. `;
    19. exports[`Link changes the class when hovered 3`] = `
    20. <a
    21. className="normal"
    22. href="http://www.facebook.com"
    23. onMouseEnter={[Function]}
    24. onMouseLeave={[Function]}>
    25. Facebook
    26. </a>
    27. `;

    下次你运行测试时,渲染的结果将会和之前创建的快照进行比较。 代码变动时快照必须按顺序提交。 当快照测试失败,你需要去检查是否是你想要或不想要的变动。 如果变动符合预期,你可以通过jest -u调用Jest从而重写存在的快照。

    该示例代码在

    快照测试与 Mocks, Enzyme 和 React 16

    There's a caveat around snapshot testing when using Enzyme and React 16+. If you mock out a module using the following style:

    1. jest.mock('../SomeDirectory/SomeComponent', () => 'SomeComponent');

    Then you will see warnings in the console:

    React 16 triggers these warnings due to how it checks element types, and the mocked module fails these checks. Your options are:

    • Render as text. This way you won't see the props passed to the mock component in the snapshot, but it's straightforward:jsjest.mock('./SomeComponent', () => () => 'SomeComponent');

    • Render as a custom element. DOM "custom elements" aren't checked for anything and shouldn't fire warnings. They are lowercase and have a dash in the name.jsjest.mock('./Widget', () => 'mock-widget');

    • Use react-test-renderer. The test renderer doesn't care about element types and will happily accept e.g. SomeComponent. You could check snapshots using the test renderer, and check component behavior separately using Enzyme.

    如果你想要断言和操纵您渲染的组件你可以使用 或 React 的 TestUtils。本例中我们使用 Enzyme。 本例中我们使用 Enzyme。

    You have to run yarn add —dev enzyme to use Enzyme. If you are using a React version below 15.5.0, you will also need to install react-addons-test-utils.

    Let's implement a checkbox which swaps between two labels:

    1. // CheckboxWithLabel.js
    2. import React from 'react';
    3. export default class CheckboxWithLabel extends React.Component {
    4. constructor(props) {
    5. super(props);
    6. this.state = {isChecked: false};
    7. // bind manually because React class components don't auto-bind
    8. // http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding
    9. this.onChange = this.onChange.bind(this);
    10. }
    11. }
    12. render() {
    13. return (
    14. <label>
    15. <input
    16. type="checkbox"
    17. checked={this.state.isChecked}
    18. onChange={this.onChange}
    19. />
    20. {this.state.isChecked ? this.props.labelOn : this.props.labelOff}
    21. </label>
    22. );
    23. }
    24. }

    在这个例子中我们使用了 Enzyme 的。

    1. // __tests__/CheckboxWithLabel-test.js
    2. import React from 'react';
    3. import {shallow} from 'enzyme';
    4. import CheckboxWithLabel from '../CheckboxWithLabel';
    5. test('CheckboxWithLabel changes the text after click', () => {
    6. // Render a checkbox with label in the document
    7. const checkbox = shallow(<CheckboxWithLabel labelOn="On" labelOff="Off" />);
    8. expect(checkbox.text()).toEqual('Off');
    9. checkbox.find('input').simulate('change');
    10. expect(checkbox.text()).toEqual('On');
    11. });

    The code for this example is available at examples/enzyme.

    If you need more advanced functionality, you can also build your own transformer. Instead of using babel-jest, here is an example of using babel:

    1. // custom-transformer.js
    2. 'use strict';
    3. const babel = require('babel-core');
    4. const jestPreset = require('babel-preset-jest');
    5. module.exports = {
    6. process(src, filename) {
    7. if (babel.util.canCompile(filename)) {
    8. return babel.transform(src, {
    9. filename,
    10. presets: [jestPreset],
    11. });
    12. }
    13. return src;
    14. },
    15. };

    不要忘记安装 babel-corebabel-preset-jest 包使这个例子可以工作。

    为了使这个与 Jest 一起工作,您需要更新您的 Jest 配置:。