Jest 常见问题
bash npm install --save-dev jest
或
```bash
yarn add --dev jest
随后在 package.json 中添加测试脚本:
"scripts": {
"test": "jest"
}
即可通过 npm test 运行测试。
如何让 Jest 支持 TypeScript?
安装以下依赖:
npm install --save-dev jest typescript ts-jest @types/jest
然后使用 ts-jest 预设的配置:
npx ts-jest config:init
或手动创建 jest.config.js:
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
如何配置 Jest 使用 Babel 转换代码?
安装 Babel 相关依赖:
npm install --save-dev babel-jest @babel/core @babel/preset-env
在项目根目录创建 babel.config.js:
module.exports = {
presets: ['@babel/preset-env'],
};
Jest 会自动检测 babel-jest 并使用该配置转换 JavaScript 文件。
基本使用与匹配器
常见的断言匹配器有哪些?
toBe(value):严格相等(===)toEqual(value):递归比较对象或数组的值toBeNull():检查是否为nulltoBeDefined():检查非undefinedtoBeTruthy()/toBeFalsy():检查布尔上下文转换结果toContain(item):数组或字符串是否包含某项toThrow(error?):函数是否抛出错误
toBe 与 toEqual 有什么区别?
toBe 使用 Object.is 比较,对于对象类型只检查引用是否相同。
toEqual 会递归比较对象的每个属性,常用于匹配值相同但引用不同的对象。
const a = { name: 'jest' };
const b = { name: 'jest' };
expect(a).toBe(a); // 通过
expect(a).toBe(b); // 失败
expect(a).toEqual(b); // 通过
异步测试
如何测试异步代码?
Jest 需要知道异步操作何时完成,有几种方式:
- 回调形式:使用
done回调test('异步回调', done => { fetchData((data) => { expect(data).toEqual('result'); done(); }); }); - Promise 返回:直接返回 Promise
test('Promise 测试', () => { return fetchData().then(data => { expect(data).toEqual('result'); }); }); - async/await
test('async/await', async () => { const data = await fetchData(); expect(data).toEqual('result'); });
异步测试超时怎么办?
默认超时为 5 秒,可在测试中通过第三个参数调整:
test('长时间操作', async () => {
// ...
}, 10000); // 10秒超时
或在 jest.config.js 中配置全局 testTimeout:
module.exports = {
testTimeout: 10000,
};
Mock 与 Spy
如何模拟一个模块?
使用 jest.mock(...) 自动模拟整个模块:
jest.mock('./api');
import { fetchUser } from './api';
// 所有导出方法都变为了 jest.fn()
fetchUser.mockResolvedValue({ name: 'John' });
如何只模拟模块中的特定方法,而保持其他部分真实?
使用 jest.requireActual 获取真实模块,再通过 spyOn 添加模拟:
import * as utils from './utils';
jest.spyOn(utils, 'fetch').mockResolvedValue('mocked');
// 其他方法仍为真实实现
jest.fn() 与 jest.spyOn() 的区别?
jest.fn():创建一个全新的模拟函数,可自定义实现、返回值。jest.spyOn(object, method):监听对象原有方法,并可以控制其实现,同时保留原始方法(可通过mockRestore()恢复)。
如何验证 Mock 函数的调用情况?
const mockFn = jest.fn();
mockFn('arg1', 'arg2');
expect(mockFn).toHaveBeenCalled(); // 是否被调用过
expect(mockFn).toHaveBeenCalledTimes(1); // 调用次数
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2'); // 调用参数
快照测试
什么是快照测试,怎么用?
快照测试用于记录组件的渲染输出或对象的序列化值,下次运行时进行比较。
首次运行会生成 .snap 文件,后续测试时发现差异会报错。
test('组件渲染快照', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});
使用 toMatchInlineSnapshot() 可将快照内联在测试文件中。
如何更新过时的快照?
运行 Jest 并加上 --updateSnapshot 或 -u 标志:
npx jest -u
在 watch 模式下可以按 u 键更新。
覆盖率与报告
如何生成测试覆盖率报告?
在命令行添加 --coverage:
npx jest --coverage
或在 jest.config.js 中设置 collectCoverage: true。
报告会生成在 coverage/ 目录,lcov-report/index.html 可在浏览器中查看。
如何只收集部分文件或忽略某些文件?
配置 collectCoverageFrom:
collectCoverageFrom: [
'src/**/*.{js,jsx}',
'!src/**/*.test.{js,jsx}',
'!src/vendor/**',
],
使用 ! 排除不需要统计的文件。
测试环境与调试
如何切换测试环境?(例如从 jsdom 改为 node)
在配置文件修改 testEnvironment:
module.exports = {
testEnvironment: 'node', // 或 'jsdom'
};
如果部分测试文件需不同环境,可在文件顶部使用文档块注释:
/**
* @jest-environment jsdom
*/
如何在 VS Code 中调试 Jest 测试?
在 .vscode/launch.json 添加配置:
{
"type": "node",
"request": "launch",
"name": "Jest Current File",
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
"args": ["${fileBasenameNoExtension}", "--runInBand"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
然后在测试文件中打断点,按 F5 即可调试。
常见报错与解决
Jest encountered an unexpected token
通常是因为 Jest 无法解析某些语法(如 JSX、TypeScript、CSS 模块等)。
解决:配置合适的 transformer,例如对于 CSS 模块,在 jest.config.js 中添加:
moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
},
并确保 __mocks__/styleMock.js 导出一个空对象。
测试文件没有被找到?
检查 Jest 的默认匹配模式:它查找 __tests__ 目录下所有文件,以及 .test.js 或 .spec.js 后缀的文件。
可通过配置 testMatch 或 testRegex 自定义:
testMatch: ['**/?(*.)+(test).[jt]s?(x)'],