用 Jest 写第一个 test 函数需安装 jest、命名文件为 .test.js 或 .spec.js,用 test() 包裹断言,expect() 后接匹配器如 toBe()。

怎么用 Jest 写第一个 test 函数
Jest 是当前最主流的 JavaScript 单元测试框架,开箱即用,不用配 Babel 或打包工具就能跑 ES6+ 语法。写测试前先确保项目里装了 Jest:npm install --save-dev jest,并在 package.json 的 scripts 里加一行:"test": "jest"。
测试文件名必须以 .test.js 或 .spec.js 结尾(比如 math.test.js),Jest 才会自动识别。每个测试用 test() 或 it() 包裹,第一个参数是描述性字符串,第二个是回调函数:
test('add(1, 2) returns 3', () => {
expect(add(1, 2)).toBe(3);
});注意:expect() 后面必须跟匹配器(如 toBe()、toEqual()),不能直接写 add(1, 2) === 3——那样失败时没错误堆栈,也看不到期望值与实际值的差异。
describe() 和 beforeEach() 怎么组织多个测试用例
当一个模块有多个函数或同一函数有多种输入场景时,用 describe() 分组能让测试结构清晰,报错时也更容易定位到哪一组出问题。它不改变执行逻辑,只是语义分组:
立即学习“Java免费学习笔记(深入)”;
describe('User validation', () => {
test('rejects empty name', () => { /* ... */ });
test('accepts valid email', () => { /* ... */ });
});如果多个测试共用某个对象或状态(比如初始化一个 new UserService() 实例),用 beforeEach() 比在每个 test() 里重复创建更安全、更易维护:
- 避免测试间状态污染(比如某个测试修改了全局变量或实例属性)
- 所有测试从干净状态开始,结果可重现
- 如果初始化耗时,还可以考虑
beforeAll(),但得小心副作用
异步代码怎么测?async/await 和 Promise 的写法区别
Jest 默认等待测试函数同步执行完就结束,遇到异步操作会直接跳过断言,导致“测试通过但其实没跑”。必须显式告诉 Jest:等我这个异步动作完成再判结果。
三种合法写法(任选其一):
- 返回
Promise:在test()回调里return fetch('/api').then(...) - 用
async/await:函数声明为async,里面用await等待,Jest 自动识别 - 传入
done回调:在函数参数里加done,手动调用done()表示完成(容易忘调,不推荐)
错误示范:test('fetches user', () => { fetch('/user').then(res => expect(res.ok).toBe(true)); }); —— 这个 expect 永远不会被 Jest 等待,测试必然“假通过”。
为什么 mock 不生效?常见陷阱在哪
Mock 的核心是“替换真实依赖”,但 Jest 的 jest.mock() 是**自动 hoist 到文件顶部**的,这意味着你不能在 require 或 import 之后才调用它——那样模块已经加载完了,mock 失效。
正确做法只有两种:
- 把
jest.mock('axios')放在import语句之后、任何测试代码之前(Jest 会自动提升,但写在上面更直观) - 用工厂函数形式动态控制返回值:
jest.mock('axios', () => ({ get: jest.fn().mockResolvedValue({ data: 'ok' }) }));
另一个高频坑:mock 模块里的默认导出(export default)时,要 mock 整个模块,而不是只 mock 某个方法名;ESM 下还要注意 __esModule: true 兼容性,有时得用 jest.requireActual() 保留部分真实行为。
真实项目里,边界越清晰(比如 API 调用全收口在 service 层)、mock 越简单;把 fetch 直接塞进组件里,后续就只能靠 msw 拦网络请求,成本高得多。











