首页 > 技术文章 > 给 React + TS 项目添加 Jest 测试

babywhale 2020-08-04 10:51 原文

以 react + ts 的组件库项目为例,记录 jest 安装配置及测试的过程。

一、安装配置

安装 jest

npm install jest -D

生成配置文件

npx jest --init

按照引导进行选择后,会创建配置文件 jest.config.js,并在 package.json 中添加命令脚本 test: jest

支持 babel

要想支持 ts 和 react,都需要先支持 babel,从而在测试环境中转换代码

npm install babel-jest @babel/core @babel/preset-env -D
// .babelrc
{
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        }
      }
    ]
  ]
}

支持 ts

npm install @babel/preset-typescript -D
// .babelrc
{
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        }
      }
    ],
    '@babel/preset-typescript'  // 添加这个
  ]
}

支持 react

npm install @babel/preset-react -D
// .babelrc
{
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        }
      }
    ],
    '@babel/preset-typescript'  
    '@babel/preset-react' // 添加这个
  ]
}

使用 react 测试工具 enzyme

添加 enzyme

npm install enzyme enzyme-adapter-react-16 -D

项目中新建 tests/jest.setup.js 文件

// jest.setup.js

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

并在 jest.config.js 中配置

setupFiles: ['./tests/jest.setup.js']

二、快照测试

  • 使用 react-test-renderer

添加 react-test-renderer 用于快照测试

npm install react-test-renderer -D

下面给 Button 组件添加测试试一下

// components/button/__test__/index.test.js

import React from 'react';
import renderer from 'react-test-renderer';
import Button from '../Button';

describe('Button 组件', () => {
    it('正确渲染 Button 组件', () => {
        const button = renderer.create(<Button>button</Button>).toJSON();
        expect(button).toMatchSnapshot();
    });
});

执行 npm run test

可以看到有一个快照被生成了

再执行一遍 npm run test,这次没有写快照了,并且匹配通过了

  • 也可以用 enzyme 来进行快照测试(推荐)

添加 enzyme-to-json,用于将 enzyme 构造的 wrapper 转变成能够支持快照测试的格式。

npm install enzyme-to-json -D

同样,测试一下 Button 组件

// components/button/__test__/index.test.js

import React from 'react';
import Button from '../Button';
import { render } from 'enzyme';
import toJson from 'enzyme-to-json';

describe('Button 组件', () => {
    it('正确渲染 Button 组件', () => {
        const button = render(<Button>button</Button>);
        expect(toJson(button)).toMatchSnapshot();
    });
});

执行 npm run test,没通过,因为跟之前react-test-renderer渲染的快照不匹配了

我们需要重新写快照,执行npx jest -u

快照更新了,再执行一下npm run test,通过了

代码中的 toJson 部分可以统一配置到 jest.config.js,添加快照序列化配置,代码里就不用写 toJson 了。

snapshotSerializers: ['enzyme-to-json/serializer']

三、事件测试

利用 mock 函数 测试一下 Button 组件的事件

// components/button/__test__/index.test.js

import React from 'react';
import Button from '../Button';
import { render, mount } from 'enzyme';

describe('Button 组件', () => {
    it('正确渲染 Button 组件', () => {
        const button = render(<Button>button</Button>);
        expect(button).toMatchSnapshot();
    });

    it('测试 Button 组件 loading 参数', () => {
        const fn = jest.fn();
        const loadingButton = mount(
            <Button loading onClick={fn}>
                loading button
            </Button>
        );
        expect(loadingButton).toMatchSnapshot();
        loadingButton.find('button').simulate('click');
        expect(fn).not.toBeCalled();
    });

    it('测试 Button 组件 disabled 参数', () => {
        const fn = jest.fn();
        const disabledButton = mount(
            <Button disabled onClick={fn}>
                disabled button
            </Button>
        );
        expect(disabledButton).toMatchSnapshot();
        disabledButton.find('button').simulate('click');
        expect(fn).not.toBeCalled();
    });

    it('测试 Button 组件 onClick 事件', () => {
        const fn = jest.fn();
        const button = mount(<Button onClick={fn}>button</Button>);
        button.find('button').simulate('click');
        expect(fn).toBeCalled();
    });
});

四、参考文档

jest 官方文档
npm: enzyme

推荐阅读