背景
最近在做如何提升代码质量的事情,有个思路是通过增加单侧来减少bug量的方式,于是就在现有的项目中接入jest+enzyme来实现纯函数的单侧以及针对react组件的测试用例,本来感觉很简单的,但是在真实操作中还是遇到了好多坑,自己一步一步摸索出来终于搞定了,把踩坑经历分享出来供大家参考。
踩坑经历
项目信息
react@16.14.0+react-router@3.2.6+typescript@4.9.5
接入单测工具信息
jest@29.7.0+enzyme@3.11.0+enzyme-adapter-react-16@1.15.7
babel配置
首先需要配置babel信息来支持ts以及jsx,tsx文件编辑为js文件
在根目录创建babel.config.js文件,文件内容如下,@babel/preset-env包用来转换es6,@babel/preset-react用来转换react组件,@babel/preset-typescript用来转换ts
// babel.config.js
{
"presets": [["@babel/preset-env"], ["@babel/preset-react"], "@babel/preset-typescript"]
}
纯函数测试
增加完jest+enzyme后就可以创建测试用例了,我直接用的jest默认配置,及创建__tests__文件夹来标识是单侧文件,找了一个纯函数来测试,执行成功,感觉有点太easy了,然而头疼的在后头呢
import { test, expect } from '@jest/globals';
import { getBpmStatusIconConfig } from '../helper';
test('测试demo', () => {
expect(getBpmStatusIconConfig(1)).toEqual({
class: '',
iconType: 'more-circle-fill',
});
});
react组件测试
然后就开始找简单的react组件做测试,首先想试用一下快照测试,然后就遇到了各种问题
mount函数支持报错
问题原因:
需要利用浏览器能力渲染出来真实dom,然后在node环境是无法渲染的,这句需要借助于jsdom库来模拟生成
解决方案:
-
运行一下命令安装
npm i -D jsdom jsdom-global注意:jsdom版本与react版本是有对应关系的,我使用的react@16.14.0,对应的jsom@11.12.0;我直接装最新版本的会报错,目前还没找到对应关系是啥,只是找到与react@16.14.0发布相似时间点的版本测试(灵感来源于使用react-test-renderer版本报错,查阅资料发现他是react包提供的功能,需要独立版本与react保持一致才行)
-
在入口文件setupFiles.js文件中通过 require('jsdom-global/register'); 加载,这样就可以在所有的单侧文件中有jsdom环境(推荐);还可以单文件引入该包
提示需要适配器
问题原因:
jest中使用enzyme,需要增加enzyme-adapter-react-15适配器
解决方案:
-
新建入口文件setupFiles.js
// setupFiles.js const { configure } = require('enzyme'); const Adapter = require('enzyme-adapter-react-16'); require('jsdom-global/register'); configure({ adapter: new Adapter() }); -
在jest配置中指定入口文件
// package.json文件 "jest": { "setupFilesAfterEnv": [ "<rootDir>/dev/test/setupFiles.js" ], }
无法识别scss文件
问题原因:
scss样式文件无法识别
解决方案:
在jest配置(我使用的是在package.json中加jest配置,也可使用独立文件方式)中增加moduleNameMapper转换,记得添加对应的目录及文件(如:/dev/test/__mocks__/fileMock.js)
// package.json文件
"jest": {
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/dev/test/__mocks__/fileMock.js",
"\\.(css|scss)$": "<rootDir>/dev/test/__mocks__/styleMock.js"
}
}
// fileMock.js 文件
module.exports = 'test-file-stub';
// styleMock.js文件
module.exports = {};
快照内容不是真实dom结构而是js对象
import React from 'react';
import { mount } from 'enzyme';
import { describe, test, expect } from '@jest/globals';
import NoPermission from '../index';
describe('NoPermission组件单侧', () => {
test('快照测试', () => {
// const tree = renderer.create(<NoPermission description="页面存在错误" title="提示" />).toJSON();
const tree = mount(<NoPermission description="页面存在错误" title="提示" />);
expect(tree.render()).toMatchSnapshot();
});
});
问题原因:
enzyme的mount需要通过enzyme-to-json来转成dom的json
解决方案:
-
安装enzyme-to-json包
-
在jest配置中增加配置
// package.json "jest": { "snapshotSerializers": [ "enzyme-to-json/serializer" ] }
组件中有加载三方包报错
问题原因:
-
node_modules中的包为esm,需要配置对应的babel配置,配置了.babelrl.json不生效
-
部分包存在编辑的问题(老的业务自定义的包,还不确定为什么提示加载报错)
babel配置内容只针对业务代码有效,不对node_modules文件有有效,如一些包需要在业务代码中编译
参考文章: juejin.cn/post/703262…
解决方案:
-
.babelrl.json对jest不起作用改为使用babel.config.js就可以了
-
设置jest配置在运行时实时做编辑
// package.json { "jest":{ "transformIgnorePatterns": [ "<rootDir>/node_modules/(?!(@common/utils)/)" ] } }