前言
最近在学习使用React Testing Library,但是官方的安装和配置流程比较模糊,需要自己去Jest寻找做相应的配置,故本文用以记录一般的配置流程,其中包含babel、React、Typescript、CSS配置的解决。
若使用CRA(Create React App)创建的项目,则直接安装React Testing Library即可,本文记录的为非CRA创建项目。
项目初始化
此仓库是非CRA创建的项目:rtl-setup。你可以直接倒退到“init” commit后再跟随步骤进行
开始配置
第一步:安装Jest、React testing library
npm install --save-dev @testing-library/react jest
第二步:生成Jest配置
通过全局的Jest命令行,在项目下生成Jest配置。
先全局安装Jest
npm install -g jest
接着在对应项目下生成Jest配置
jest --init
根据自己需要选择选项即可
第三步:解决框架配置问题
这一步是比较多样化的,主要是对Jest的配置,需要根据项目状况来进行配置,比如是否使用了Typescript、是否已经配置好了babel。本文按照项目情况,根据babel、React、CSS Module、Typescript进行配置。
其中很多babel preset项目中可能已经安装好了,但为了流程流畅,本文中依然会将对应的preset列出。
babel配置
原项目中可能已有babel配置,若无,按照文档添加即可。
首先安装依赖:
npm install --save-dev babel-jest @babel/core @babel/preset-env
接着在babel.config.js中添加对应的presets:
// babel.config.js
module.exports = {
presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};
后续React、Typescript的preset也需要在babel.config.js中进行相应的配置。
React配置
安装对应依赖
npm install --save-dev @babel/preset-react
对应的babel.config.js配置
// babel.config.js
module.exports = {
presets: [['@babel/preset-env', {targets: {node: 'current'}}], '@babel/preset-react'],
};
typescript支持
Jest可以支持使用Typescript书写单元测试,只需要通过babel配置对应的Typescript preset即可,故安装对应的依赖:
npm install --save-dev @babel/preset-typescript
对应的babel.config.js配置
// babel.config.js
module.exports = {
presets: [
["@babel/preset-env",{"targets": {"node": "current"}}],
"@babel/preset-react",
"@babel/preset-typescript"
],
};
此后就可以用Typescript写单测了,书写单测的过程中若提示没有安装对应的types,按照提示安装即可。
Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha`.
这里仅需安装@types/jest。
CSS module
Jest本身不知道如何处理不同扩展的文件,对于CSS Module或者Less Module等,可以通过Jest的moduleNameMapper进行处理。
假设为进行相应的配置,直接引入css文件跑测试可能出现以下问题:
SyntaxError: Unexpected token '.'
1 | import React from 'react';
> 2 | import './index.css';
官方也给出了相应的解决方案:使用ES6 Proxy来模拟CSS Modules。
首先安装identity-obj-proxy:
npm install --save-dev identity-obj-proxy
然后进行配置Jest的moduleNameMapper属性(在jest.config.js中或者package.json中)即可。
moduleNameMapper: {
"\\.(css|less)$": "identity-obj-proxy"
}
testing-library/jest-dom配置
到目前为止我们的测试环境已经可以基本跑通,但是实际开发测试中还是不能满足的,比如需要判断一个元素是否在页面中需要用到APItoBeInTheDocument
,如果这时没有配置jest-dom则会报错:expect(...).toBeInTheDocument is not a function
,接下来就进行jest-dom的配置。
首先安装@testing-library/jest-dom:
npm install --save-dev @testing-library/jest-dom
接着创建setupTest.ts(或者setupTest.js)文件在src目录下(或者你喜欢的目录),写入代码:
import '@testing-library/jest-dom/extend-expect';
最后在jest.config.js
中找到如下属性写入你的文件路径:
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
如此便可顺利跑通。
其他可选配置
这部分的配置不是必须的,仅仅是个人在使用中发现的一些问题,可选进行
test.(js|ts)排除
Jest默认匹配的单元测试文件:
- __tests__文件夹下的.js、.ts、.jsx、.tsx
- .test.(js|ts|jsx|tsx)、.spec.(js|ts|jsx|tsx)
- test.(js|ts|jsx|tsx)、spec.(js|ts|jsx|tsx)
由于某些开发者喜欢写test.js这样的文件名,但又不是单元测试,故个人想把诸如test.js此类无前缀的文件直接排除,只需要在jest配置的testMatch属性进行相应的修改。
testMatch属性是使用micromatch表示的,并非正则表达式,其默认值为:
testMatch:[
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[jt]s?(x)"
]
根据micromatch文档,只需将\*\*/?(*.)
中的·?改成+即可
testMatch: [
"**/__tests__/**/*.[jt]s?(x)",
"**/+(*.)+(spec|test).[tj]s?(x)"
],
测试
最后写一个示例组件与单测进行测试:
// test/example/Example.tsx
import React from 'react';
import './index.css';
const title = 'Hello React';
function Example() {
return <div>{title}</div>;
}
export default Example;
// test/example/Example.test.tsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import Example from './Example';
describe('App', () => {
test('renders App component', () => {
render(<Example />);
expect(screen.getByText('Hello React')).toBeInTheDocument();
});
});
使用npm run test
开始测试。
// package.json
"scripts": {
"test": "jest",
....
结果:
PASS test/example/Example.test.tsx
App
✓ renders App component (22 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.194 s
Ran all test suites.
结语
经过以上配置,一个非CRA创建的React项目即可跑通Jest + React Testing Library,根据实际项目情况可适当做调整。
仓库地址:Joeoeoe/rtl-setup
参考资料
React Testing Library
Jest——additional-configuration
Jest——babel
Jest——React
Jest——Typescript
Jest——mocking css modules
Jest——testmatch-arraystring
syntaxerror with jest and react and importing css files
react testing library why is tobeinthedocument not a function
react-testing-library why is toBeInTheDocument() not a function