今天来看一下如何在React项目中使用Jest进行单元测试。
创建React项目
我们使用Vite来创建React项目,命令如下:
1 | npm create vite@latest react-app-jest --template react-ts |
使用VSCode打开项目
使用如下命令打开项目
1 | cd react-app-jest |
安装初始依赖
打开VSCode,选择菜单中的Terminal | New Terminal
(或者快捷键Ctrl + Shift + `
)打开一个新的terminal,运行以下命令安装初始依赖:
1 | npm install |
运行项目
运行以下命令来启动项目,确保项目可以正常运行。
1 | npm run dev |
安装Jest相关的依赖
需要安装的依赖很多,运行以下命令来安装, npm i -D
相当于npm install --save-dev
.
1 | npm i -D jest @types/jest ts-jest @testing-library/react @testing-library/jest-dom @testing-library/user-event jest-environment-jsdom ts-node |
分别解释一下上面的包都有什么作用:
jest
:Jest是一个JavaScript测试框架,主要用于单元测试和集成测试。@types/jest
:Jest的TypeScript类型定义文件。ts-jest
:Jest的TypeScript预处理器,允许你在Jest中使用TypeScript。@testing-library/react
:React Testing Library是一个用于测试React组件的库,提供了一些实用的工具和方法。@testing-library/jest-dom
:提供了一些自定义的Jest匹配器,用于测试DOM节点的状态。jest-environment-jsdom
:Jest的JS DOM环境,允许你在Node.js中模拟浏览器环境。@testing-library/user-event
:提供了一些实用的工具和方法,用于模拟用户事件。它比@testing-library/react
中内置的fireEvent
更好用。ts-node
:TypeScript执行器,允许你在Node.js中直接运行TypeScript代码。Jest通过这个模块来读取jest.config.ts
文件。
配置Jest
jest.setup.ts
在src
目录下创建文件test.setup.ts
,这个文件用来导入@testing-library/jest-dom
,内容如下:
1 | import '@testing-library/jest-dom'; |
mock文件
在项目根目录下创建一个mock
文件夹,里面添加一个文件fileMock.ts
,这个文件主要用来处理svg, gif, css等非javascript/json格式的文件,内容如下:
1 | module.exports = { |
在项目根目录下创建一个jest.config.ts
文件,内容如下:
1 | import { Config } from 'jest'; |
tsconfig.json配置
添加如下内容到项目根目录下的tsconfig.json
文件中。
1 | "compilerOptions": { |
创建测试文件
首先修改一下src/App.tsx
文件,让它渲染一个h1
标签,内容是Hello, world!
。
1 | <h1>Hello, world!</h1> |
然后在src
目录下创建一个测试文件App.test.tsx
,内容如下:
1 | import { render, screen } from '@testing-library/react'; |
运行测试
通过命令行运行
首先配置package.json
,在package.json
中添加以下脚本:
1 | "scripts": { |
然后在终端中运行以下命令来运行测试:
1 | npm run test |
如果你想查看测试覆盖率,可以运行以下命令:
1 | npm run test:coverage |
通过Jest插件运行测试
有两个常用的Jest插件可以使用,一个是Jest
,另一个是Jest Runner
。这两个插件都可以在VSCode的扩展市场中找到。
安装以后,打开测试文件App.test.tsx
,你会看到每个测试用例旁边都有一个绿色的运行按钮,点击它就可以运行测试了。
也可以使用鼠标右键菜单中的Run Jest
来运行测试。
troubleshooting
Support for the experimental syntax ‘jsx’ isn’t currently enabled
SyntaxError: Private field ‘#root’ must be declared in an enclosing class
如果遇到如下错误,仔细观察错误产生的位置,是在import App.css的地方,说明是css文件的问题。
1 | SyntaxError: Private field '#root' must be declared in an enclosing class |
将CSS文件格式添加到jest.config.ts
文件中的moduleNameMapper
区块中,内容如下:
1 | moduleNameMapper: { |
require() of ES modules is not supported.
如果你遇到了如下错误,是因为你的jest.config.ts
文件是ES Module格式的,而Jest默认使用CommonJS格式来解析配置文件。欲知详情请查看这里
1 | Error: Jest: Failed to parse the TypeScript config file D:\personal\codes\react\vite-react-app-jest\jest.config.ts |
解决办法也很简单,因为Jest的配置文件支持多种格式,我们姑且不实用ts格式,而是使用js格式来编写配置文件。将jest.config.ts
文件重命名为jest.config.js
,并将文件内容修改为如下:
1 | const config = { |
如此这般,Jest就不会在使用ts-node
来解析配置文件了,也就不会再报上面的错误了。
Aggregate Error:
这个错误非常的诡异,出现的场景也不尽相同,我至今没有搞懂这个错误的根源到底是什么。
1 | AggregateError |
AggregateError是一个内置的JavaScript错误类型,表示多个错误的集合。这个错误通常是由于Promise.all()方法中的多个Promise被拒绝时抛出的。详情可以看这里
处理办法:
在test.setup.ts
文件中添加如下代码:
1 | Object.defineProperty(window, 'matchMedia', { |