Jest 常见问题

FreeGuideOnline 最新 2026-07-14

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():检查是否为 null
  • toBeDefined():检查非 undefined
  • toBeTruthy() / toBeFalsy():检查布尔上下文转换结果
  • toContain(item):数组或字符串是否包含某项
  • toThrow(error?):函数是否抛出错误

toBetoEqual 有什么区别?

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 需要知道异步操作何时完成,有几种方式:

  1. 回调形式:使用 done 回调
    test('异步回调', done => {
      fetchData((data) => {
        expect(data).toEqual('result');
        done();
      });
    });
    
  2. Promise 返回:直接返回 Promise
    test('Promise 测试', () => {
      return fetchData().then(data => {
        expect(data).toEqual('result');
      });
    });
    
  3. 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 后缀的文件。
可通过配置 testMatchtestRegex 自定义:

testMatch: ['**/?(*.)+(test).[jt]s?(x)'],