把 Jest 集成到 HelloWorld 项目,关键是把测试目标弄清楚、装好依赖、处理转译(Babel 或 TypeScript)、配置测试运行脚本与覆盖率,然后在 CI 环境里稳定运行。下面按实操步骤来,从零开始安装、写第一个测试、处理常见模块与静态资源问题、到进阶的快照、异步测试和覆盖率配置,让你能边学边试,立刻看到效果。


为什么要在 HelloWorld 项目里用 Jest?
想象一下,代码像是一列火车,测试就是每节车厢的安全检查。Jest 提供断言、模拟、快照与覆盖率工具,让你在改动后能快速确认行为没变。它启动快、默认配置友好,社区插件多,适合前端(React、Vue)和 Node 工程。
开始前的准备
- 确保项目能用 npm 或 yarn 安装依赖。
- 知道项目语言:纯 JavaScript、Babel 转译、还是 TypeScript。
- 决定运行环境:本地测试还是 CI(GitHub Actions、GitLab CI、Jenkins 等)。
安装 Jest(基础)
先在项目根目录执行安装命令。下面给出常用两种包管理器的写法:
| npm | npm install –save-dev jest |
| yarn | yarn add –dev jest |
然后在 package.json 的 scripts 里加一条:
{
"scripts": {
"test": "jest"
}
}
第一步:写第一个测试文件
在项目中新建 __tests__/hello.test.js:
const sayHello = require('../src/sayHello');
test('sayHello 返回 Hello, World!', () => {
expect(sayHello()).toBe('Hello, World!');
});
再写实现文件 src/sayHello.js:
module.exports = function() {
return 'Hello, World!';
};
运行 npm test,你应该看到绿色通过信息。
Babel 支持(如果你使用 ESModules 或现代语法)
如果代码用到了 import/export、class fields、optional chaining 等语法,需要 Babel 给 Jest 转译。步骤:
- 安装 Babel 相关依赖:
npm install --save-dev @babel/core @babel/preset-env babel-jest
- 在项目根目录创建 .babelrc 或 babel.config.js,例如:
{
"presets": ["@babel/preset-env"]
}
Jest 会自动使用 babel-jest 来转译,通常无需额外配置。如果你用 TypeScript,下面有专门一节。
TypeScript 支持
用 TypeScript 的话,可以选择两个常见方案:
- 用 ts-jest 直接在测试时转译 TypeScript。
- 先用 tsc 编译到 JavaScript,再对输出运行 Jest(不太方便)。
推荐方案:ts-jest,安装并配置:
npm install --save-dev ts-jest @types/jest typescript
npx ts-jest config:init
这会在项目根创建 jest.config.js,里面包含 TypeScript 的 transform 配置。然后把测试文件用 .ts/.tsx 写就可以了。
React 项目:处理 JSX 与组件快照
React 项目常配合 react-test-renderer 或 @testing-library/react:
npm install --save-dev @testing-library/react react-test-renderer
示例快照测试:
import React from 'react';
import renderer from 'react-test-renderer';
import MyButton from '../MyButton';
test('MyButton 快照', () => {
const tree = renderer.create( ).toJSON();
expect(tree).toMatchSnapshot();
});
运行时,Jest 会在 __snapshots__ 文件夹生成快照文件,方便后续对比。
常见配置项速查(jest.config.js 模板)
module.exports = {
testEnvironment: 'node', // 或 'jsdom' 用于浏览器环境
transform: {
'^.+\\.(js|jsx)$': 'babel-jest', // 或 ts-jest
},
moduleNameMapper: {
'\\.(css|less|scss)$': 'identity-obj-proxy', // 静态资源/样式 mock
},
collectCoverage: true,
coverageDirectory: 'coverage',
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
};
处理静态资源与模块别名
前端项目常遇到导入图片、样式或用到 webpack 别名。Jest 需要知道如何 mock 或解析:
- 样式文件:安装 identity-obj-proxy 并在 moduleNameMapper 中映射为 ‘identity-obj-proxy’。
- 图片等二进制资源:映射到一个空模块(比如 __mocks__/fileMock.js),内容导出字符串或空对象。
- 模块别名:把 webpack 的别名映射到 Jest 的 moduleNameMapper。
异步测试与定时器
异步函数可以用 async/await、done 回调或返回 Promise 来测试。例子:
test('异步请求返回数据', async () => {
const data = await fetchData();
expect(data.id).toBe(42);
});
如果你用到定时器(setTimeout、setInterval),Jest 提供假定时器:jest.useFakeTimers(),这样能快速推进时间并断言行为。
Mock(模拟)技巧
模拟是 Jest 的强项,可以把外部依赖替换成可控版本:
- jest.fn() 创建一个可监视的空函数。
- jest.spyOn(obj, ‘method’) 监视对象方法,必要时可 mock 实现。
- jest.mock(‘moduleName’) 可以把整个模块替换成 mocks 目录下的实现。
常见用法是把网络请求、文件系统、第三方 SDK mock 掉,保证测试稳定且速度快。
覆盖率(Coverage)与阈值
开启覆盖率很简单:npm test — –coverage 或在 jest.config.js 设 collectCoverage: true。推荐设定阈值,避免“覆盖率幻觉”:
coverageThreshold: {
global: {
branches: 80,
functions: 85,
lines: 90,
statements: 90,
},
},
这样当覆盖率下降时 CI 会失败,提醒你补充测试。
在 CI 中运行 Jest(以 GitHub Actions 为例)
把测试加到持续集成是必须的。简单的工作流步骤:
- checkout 代码;
- 安装依赖(npm ci 或 yarn install –frozen-lockfile);
- 运行构建步骤(如果需要转译);
- 执行 npm test — –ci –reporters=default –reporters=jest-junit(可选输出 junit)。
CI 环境常见问题包括内存不足与并发限制,必要时用 –runInBand 或调整 maxWorkers。
调试与常见问题排查
下面是一些典型问题与处理思路:
- 测试跑不起来,语法错误:检查 jest transform 是否针对目标文件配置正确(Babel/ts-jest)。
- 模块找不到:确认 moduleNameMapper 覆盖了别名与静态资源映射。
- 快照意外变更:先阅读差异,确认是合理变更再更新快照(jest -u),不要盲目更新。
- 测试在 CI 中超时或内存溢出:用 –runInBand、减少并发或提高机器规格。
一张速查表:常用命令
| 运行所有测试 | npm test |
| 带覆盖率运行 | npm test — –coverage |
| 只运行匹配文件 | npm test — -t “关键字” |
| 更新快照 | npm test — -u |
进阶用法与优化点
- 并行与工作线程:默认 Jest 会并行运行测试以提高速度,必要时调整 maxWorkers。
- 测试分片:大型项目可在 CI 中按文件或目录分片运行以缩短总时长。
- 自定义环境:如果 testEnvironment 默认的 node/jsdom 不够,可实现自定义环境扩展。
- 报告集成:把 coverage 输出、jest-junit 等集成到 CI 中,方便看报表。
写测试的小建议(实践中的心得)
- 先写最小可重现的测试:一个小函数的单元测试比复杂场景更容易定位问题。
- 把外部依赖隔离:网络请求、时间和随机数都应当 mock,保证测试稳定。
- 保持测试可读:像写文档一样命名测试,别人能从测试名看出期望行为。
- 不要把测试当成覆盖率游戏:高覆盖率是手段,不是目的,关键是捕捉真实风险。
好了,按上面步骤去做,你会先看到测试跑通,然后逐步完善配置(Babel/TypeScript、模块映射、CI 集成)。过程中如果遇到某个特定报错,常常是 transform 或 moduleNameMapper 配置不到位,按错误信息定位文件路径和 loader 配置,多试几次就能摸清楚。写到这儿,差不多把从零开始到进阶的常见场景都覆盖了,接下来就动手实践一次,边做边调,几次迭代后你会发现测试给项目带来的信心和节奏感。