浅谈Jest进行React单元测试
1.单元测试的定义测试根据不同的维度有多种分类方式,按照测试阶段主要有单元测试、集成测试和系统测试。单元测试(Unit Tesing)是针对程序的最小单位,对代码进行正确性检验的一种测试手段。在过程化编程中,最小单元是单个程序、函数、过程等;对于面向对象编程,最小单元是对象方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。
2.单元测试的意义
提升效率:通过 mock 数据,及早发现问题,而越早发现Bug,造成的浪费就会越小
结构设计:单元测试可以充当一个设计工具,有助于开发人员去思考代码结构的设计,让代码更加有利于测试。特别是先写测试,迫使我们把程序设计成易于调用和可测试的,即迫使我们解除软件中的耦合。
3.安装与配置
下文介绍使用 Jest 对 React 程序进行单元测试,采用React Testing Library 作为测试工具库。
安装Jest
yarn add --dev jest
yarn add --dev jest-environment-jsdom jest-less-loader
yarn add @testing-library/jest-dom @testing-library/react
配置Jest
jest --init
√ Would you like to use Jest when running "test" script in "package.json"? … yes
√ Would you like to use Typescript for the configuration file? … no
√ Choose the test environment that will be used for testing ? jsdom (browser-like)
√ Do you want Jest to add coverage reports? … yes
√ Which provider should be used to instrument code for coverage? ? babel
√ Automatically clear mock calls and instances between every test? … no
配置 Babel
yarn add --dev babel-jest @babel/core @babel/preset-env @babel/preset-react
在项目的根目录下创建?babel.config.js?,通过配置 Babel 使其能够兼容当前的 Node 版本。
module.exports = {
presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
'@babel/preset-react'
],
};
在package.json中配置如下内容:
"scripts": {
"test": "jest",
},
"resolutions": {
"jest-environment-jsdom": "27.4.6"
},
在jest.config.js中配置如下内容:
module.exports = {
setupFilesAfterEnv: ['@testing-library/jest-dom'],
testEnvironment: 'jsdom',
clearMocks: true,
coverageDirectory: "coverage",
moduleDirectories: [
"node_modules", "src"
],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/test/fileMock.js',
'\\.(css|less)$': '<rootDir>/test/styleMock.js',
},
transform: {
"^.+\\.(js|jsx)$": "babel-jest",
'\\.(less|css)$': 'jest-less-loader'
},
transformIgnorePatterns: [
'/node_modules/(?!antd|@ant-design|rc-.+?|@babel/runtime).+(js|jsx)$',
],
}
其中,fileMock.js与styleMock.js文件内容均为:
module.exports = {}
matchMedia.mock.js文件内容如下:
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
4.常见问题
(1)Jest encountered an unexpected token
http://www.51testing.com/attachments/2023/05/15326880_202305231341201jxCP.jpg
解决方案:
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
'\\.(css|less)$': '<rootDir>/tests/styleMock.js',
'antd/es/locale/zh_CN':'<rootDir>/tests/styleMock.js'
},
(2)无法读取 props.history.push
http://www.51testing.com/attachments/2023/05/15326880_202305231341231TC6R.jpg
解决方案:
test('test', async () => {
const mProps = { history: { push: jest.fn() } }
await render(
<AppStore {...mProps} />
)
expect(mProps.history.push).toBeCalledWith('/app/shelve')
})
页:
[1]