React(ts)搭建jest+enzyme单元测试框架

小叶子

其实参考官方文档很容易就完成搭建了,因此本文也是对官网进行一个测试搭建过程的简单演练。
https://jestjs.io/
https://enzymejs.github.io/en...

本文是根据typescript作为React开发语言的流程,使用jsx/js就不需要ts相关的接器。

安装依赖包

  • jest -- 测试框架
  • enzyme -- React的测试工具,可以使用mount、render、shallow渲染react组件,测试组件的输出、state、props等
  • babel-jest -- jest添加babel-jest后,会自动使用babel编译代码
  • @babel/core -- babel编译核心模块
  • @babel/preset-env -- 环境预设,将最新的js语言转化为es5
  • @babel/preset-react -- babel对react转换
  • @babel/preset-typescript -- babel对ts语言转换
  • enzyme-adapter-react-16 -- 用于连接react和jest的适配器,需要根据react版本下载,部分版本对照参考表格1-1
  • identity-obj-proxy -- 用于css、js文件的mock,否则会包解析不了css文件的错误
  • jsdom -- 模拟Web浏览器的子集用于测试(因为enzyme的render在构建时需要依赖window、document等bom对象)

当然为了方便开发,安装对应的types很有必要

  • @types/jest
  • @types/enzyme

enzyme-adapter-react官网上目前的版本列表,其它版本请移步官网查询
表格1-1

enzyme适配器版本React版本
enzyme-adapter-react-16^16.4.0-0
enzyme-adapter-react-16.3~16.3.0-0
enzyme-adapter-react-16.2~16.2
enzyme-adapter-react-16.1~16.0.0-0~16.1
enzyme-adapter-react-15^15.5.0
enzyme-adapter-react-15.415.0.0-0 - 15.4.x
enzyme-adapter-react-14^0.14.0
enzyme-adapter-react-13^0.13.0

babel配置文件

.babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ],
    "@babel/preset-typescript",
    "@babel/preset-react"
  ]
}

jest配置文件

jest.config.js

module.exports = {
  testEnvironment: 'node',
  roots: ['<rootDir>'],
  // 测试文件是src目录下*.test.jsx或者*.test.tsx的文件
  testRegex: 'src/(.+)\\.test\\.(jsx?|tsx?)$', 
  // 自定义转换方式,转换jsx、tsx文件
  transform: {
    '^.+\\.(j|t)sx?$': '<rootDir>/node_modules/babel-jest',
  },
  // 模块资源映射,例如alias的配置
  moduleNameMapper: {
    // 用于css、js、图片等文件的mock
    '\\.(css|less|scss)$': 'identity-obj-proxy',
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'identity-obj-proxy',
    // alias
    '^@mock/(.*)$': '<rootDir>/mock/$1',
  },
  testPathIgnorePatterns: ['\\node_modules\\'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  // 覆盖率从哪些文件收集,设置后即使0覆盖率的文件也会计算进来
  collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}', '!**/node_modules/**', '!**/dist/**'],
  // 测试报告输出地址
  coverageDirectory: '<rootDir>/coverage',
  // 在每个测试文件执行之前,运行一些代码以配置或设置测试框架。
  setupFilesAfterEnv: ['./src/test/setupTests.js'],
};

jest初始化文件

setupTests.js

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import jsdom from 'jsdom';

// 设置react和enzyme的适配器
configure({ adapter: new Adapter() });

// 配置给render挂载在global用到的dom对象
const { JSDOM } = jsdom;
const { window } = new JSDOM('');
const { document } = new JSDOM(``).window;
global.document = document;
global.window = window;

命令配置

package.json

"scripts": {
  ...
  "test": "jest"
  "test:coverage": "jest --coverage"
}

npm run test即可运行所有的单元测试
npm run test:coverage就可以运行生成覆盖率报告的单元测试

单元测试代码编写示例

测试一个checkbox组件

import { mount, ReactWrapper } from 'enzyme';
import CheckBox, { Props } from './index';
import React from 'react';

describe('CheckBox', () => {
...
it('should emit onChange corretly', () => {
    const props: Props = {
      checked: false,
      option: { label: 'test1', value: '111' },
      onChange: jest.fn(),
    };
    const wrapper = mount(<CheckBox {...props}></CheckBox>);
    wrapper.find('.checkbox-item').simulate('click');
    expect(onChange).toHaveBeenCalledWith({ checked: true, option });
  });
});

单个测试调试方法

在开发过程中,我们可能只想运行一个测试case,有2个方案可以解决

  1. 修改jest.config.js(不要提交到线上)

    module.exports = {
      ...
      // 修改为指定文件
      testRegex: 'src/(.+)\\checkbox\\.test\\.(jsx?|tsx?)$', 
  2. vscode编辑器安装插件Jest Runner
    如图,安装后每个case都可以单独运行或者调试。
    image.png
阅读 707

一只萌萌的程序媛妹子,踏入前端领域不久,希望大家多指导,欢迎大家多多指出问题

69 声望
11 粉丝
0 条评论
你知道吗?

一只萌萌的程序媛妹子,踏入前端领域不久,希望大家多指导,欢迎大家多多指出问题

69 声望
11 粉丝
宣传栏