Jest测试框架使用
Jest 简介
Jest 是什么?主要用途是?
Jest 是一个由 Facebook 维护的 JavaScript 测试框架,主要用于测试 JavaScript 和 TypeScript 代码,特别是 React 应用。它是一个 零配置(out-of-the-box) 的测试框架,提供了强大的功能,如:
- 单元测试(Unit Testing)——测试函数或模块的独立功能
- 集成测试(Integration Testing)——测试多个模块之间的交互
- 快照测试(Snapshot Testing)——检查 UI 组件的输出是否发生变化
- Mock 功能(Mocking)——模拟函数、模块、定时器、API 请求等
- 异步代码测试(Promise、
async/await
、回调)
Jest 包含了 测试运行器(Test Runner)、断言库(Assertion Library)、Mock 机制 和 覆盖率报告(Coverage Report),因此相比 Mocha、Jasmine 等框架,Jest 无需额外配置即可使用。
Jest 的主要用途
- 测试 JavaScript/TypeScript 代码
- 测试前端框架(React, Vue, Angular)
- 测试 Node.js 应用(API、数据库交互等)
- 模拟 API 请求,测试服务端交互
- 确保 UI 组件的稳定性(快照测试)
示例:基本的 Jest 测试
1
2
3
4
5
// sum.js
function sum(a, b) {
return a + b;
}
module.exports = sum;
1
2
3
4
5
6
// sum.test.js
const sum = require('./sum');
test('1 + 2 should be 3', () => {
expect(sum(1, 2)).toBe(3);
});
运行 Jest
1
npx jest
输出
1
2
PASS ./sum.test.js
✓ 1 + 2 should be 3
如何使用 Jest 运行测试?
Jest 提供了多种方式来运行测试,常见的方法如下:
1. 直接运行 Jest
如果已经安装了 Jest,可以使用以下命令运行所有测试:
1
npx jest
或在 package.json
中添加 Jest 脚本:
1
2
3
4
5
{
"scripts": {
"test": "jest"
}
}
然后执行:
1
npm test
或者:
1
yarn test
2. 运行特定的测试文件
1
npx jest sum.test.js
如果测试文件在 tests/
目录下:
1
npx jest tests/myTest.test.js
3. 运行带有特定名称的测试
可以使用 -t
选项运行匹配某个测试名称的测试:
1
npx jest -t "should return 3 when adding 1 and 2"
这将在所有测试文件中查找包含 should return 3 when adding 1 and 2
的测试,并只运行这些测试。
4. 运行测试并显示覆盖率
如果想要查看测试覆盖率:
1
npx jest --coverage
这将生成一个覆盖率报告,显示每个文件的测试覆盖率(语句、分支、函数、行数)。
5. 运行 Jest 并启用调试模式
如果需要调试 Jest 测试,可以使用:
1
node --inspect-brk node_modules/.bin/jest --runInBand
或者:
1
npx jest --runInBand --detectOpenHandles
--runInBand
让 Jest 在单个进程中运行,有助于调试。
在哪些场景下使用 jest --watch
?
jest --watch
用于监听文件变动,并在文件更改时自动重新运行测试,适用于开发过程中需要频繁修改代码和测试的场景。
使用方式
1
npx jest --watch
或者:
1
npm test -- --watch
适用场景
- TDD(测试驱动开发) —— 希望实时运行测试,并在修改代码后立即得到反馈。
- 大规模项目 —— 在大型项目中,可以减少 Jest 启动的开销,只运行受影响的测试,提高效率。
- 调试特定功能 —— 在开发某个模块时,可以专注于该模块的测试,避免重复运行所有测试文件。
- CI/CD 之外的本地开发 —— 在 CI/CD 中通常不会使用
--watch
,但本地开发时,它可以极大提高开发效率。
如果只想监听受影响的文件,可以使用:
1
npx jest --watchAll
1. 测试同步代码
同步代码测试相对简单,只需使用 Jest 的 expect()
进行断言。
示例:同步函数测试
1
2
3
4
5
// math.js
function add(a, b) {
return a + b;
}
module.exports = add;
1
2
3
4
5
6
// math.test.js
const add = require('./math');
test('adds 2 + 3 to equal 5', () => {
expect(add(2, 3)).toBe(5);
});
运行 Jest
1
npx jest
输出
1
2
PASS ./math.test.js
✓ adds 2 + 3 to equal 5
2. 测试异步代码
Jest 提供了多种方式来测试异步代码,主要有回调函数、Promise 和 async/await
。
2.1 测试使用回调函数的异步代码
如果被测试的函数接受 回调函数 作为参数,需要在 Jest 的 test()
中使用 done
来确保 Jest 在回调执行完成后才结束测试。
示例:使用回调函数
1
2
3
4
5
6
7
// fetchData.js
function fetchData(callback) {
setTimeout(() => {
callback('data received');
}, 1000);
}
module.exports = fetchData;
1
2
3
4
5
6
7
8
9
// fetchData.test.js
const fetchData = require('./fetchData');
test('fetchData returns data received', (done) => {
fetchData((data) => {
expect(data).toBe('data received');
done(); // 调用 done() 告诉 Jest 测试已完成
});
});
注意 如果 不调用 done()
,Jest 可能会在异步代码执行前就结束测试,导致测试失败或假阳性结果。
2.2 测试返回 Promise 的异步函数
如果异步函数返回 Promise,可以直接返回这个 Promise,Jest 会等待它完成。
示例:返回 Promise
1
2
3
4
5
6
7
// fetchDataPromise.js
function fetchDataPromise() {
return new Promise((resolve) => {
setTimeout(() => resolve('data received'), 1000);
});
}
module.exports = fetchDataPromise;
1
2
3
4
5
6
7
8
// fetchDataPromise.test.js
const fetchDataPromise = require('./fetchDataPromise');
test('fetchDataPromise resolves with data received', () => {
return fetchDataPromise().then((data) => {
expect(data).toBe('data received');
});
});
这里直接 return fetchDataPromise()
,Jest 会等到 Promise 解析后 才会结束测试。
2.3 测试使用 async/await
的异步代码
Jest 也支持 async/await,可以让异步测试代码更加简洁。
示例:使用 async/await
1
2
3
4
5
6
7
// fetchDataAsync.js
async function fetchDataAsync() {
return new Promise((resolve) => {
setTimeout(() => resolve('data received'), 1000);
});
}
module.exports = fetchDataAsync;
1
2
3
4
5
6
7
// fetchDataAsync.test.js
const fetchDataAsync = require('./fetchDataAsync');
test('fetchDataAsync resolves with data received', async () => {
const data = await fetchDataAsync();
expect(data).toBe('data received');
});
test()
函数前加async
,然后使用await
等待fetchDataAsync()
解析。- Jest 会自动等待
await
语句完成,不需要手动调用done()
。
2.4 测试异步代码的错误处理
如果异步代码可能会 reject,可以使用 catch
或 rejects
来测试错误情况。
示例:测试 Promise reject
1
2
3
4
5
6
7
// fetchDataError.js
function fetchDataError() {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error('network error')), 1000);
});
}
module.exports = fetchDataError;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// fetchDataError.test.js
const fetchDataError = require('./fetchDataError');
// 方式 1:使用 `.catch`
test('fetchDataError rejects with error', () => {
return fetchDataError().catch((error) => {
expect(error).toEqual(new Error('network error'));
});
});
// 方式 2:使用 Jest 提供的 `.rejects`
test('fetchDataError rejects with error', () => {
return expect(fetchDataError()).rejects.toThrow('network error');
});
// 方式 3:使用 `async/await`
test('fetchDataError rejects with error using async/await', async () => {
await expect(fetchDataError()).rejects.toThrow('network error');
});
总结
.rejects.toThrow('network error')
专门用于测试 Promise 失败的情况。- 优先使用
async/await
,让测试代码更简洁 - 使用
done()
仅用于回调函数,避免滥用 - 测试 Promise 失败时,用
.rejects.toThrow()
- 始终 return Promise,确保 Jest 正确等待异步测试完成