Jest 适合测试函数、服务层、React 组件和异步逻辑。Supertest 则专门用于测试 HTTP 接口。
Jest 断言
常用断言:
expect(value).toBe(5);
expect(obj).toEqual({ id: 1 });
expect(value).toBeTruthy();
expect(arr).toContain("x");
expect(fn).toThrow(/error/);浮点数不要直接用 toBe。
expect(0.1 + 0.2).toBeCloseTo(0.3);单元测试
业务函数:
export function applyDiscount(price: number, discount: number) {
if (discount < 0 || discount > 1) return price;
return price * (1 - discount);
}测试:
test("calculates discount", () => {
expect(applyDiscount(100, 0.2)).toBe(80);
});
test("returns original price for invalid discount", () => {
expect(applyDiscount(100, 1.5)).toBe(100);
});Mock 外部请求
Mock 的目的不是“假装测试通过”,而是隔离外部依赖,让测试只关注当前逻辑。
jest.mock("axios");
const mockedAxios = axios as jest.Mocked<typeof axios>;
mockedAxios.get.mockResolvedValueOnce({
data: { id: 1, name: "Jesse" },
});
await expect(getUser(1)).resolves.toEqual({ id: 1, name: "Jesse" });
expect(mockedAxios.get).toHaveBeenCalledWith("/users/1");常见 Mock 对象:
- 网络请求
- 数据库仓库
- 时间函数
- 随机数
- 第三方服务
异步测试
await expect(fetchUser()).resolves.toMatchObject({ id: 1 });
await expect(fetchUser()).rejects.toThrow();异步测试一定要 return 或 await Promise,否则测试可能提前结束。
Supertest 测 API
Supertest 可以不启动真实端口,直接测试 Express/Next/Nest 接口。
const res = await request(app)
.get("/user/1")
.query({ detail: "full" })
.set("Authorization", "Bearer test123");
expect(res.statusCode).toBe(200);
expect(res.body).toHaveProperty("id", "1");POST JSON:
await request(app)
.post("/login")
.send({ username: "jesse", password: "123456" })
.expect(200);API 测试重点不是只看状态码,还要断言响应结构、错误分支、权限和边界输入。
延伸理解
复习这篇时,不要只记住名词,要把重点放在 Jest 断言、Mock、异步测试、Supertest API 测试和边界条件。这类知识如果只停留在定义层面,很容易在面试或项目中答得很散。更好的理解方式是把它放进一个具体场景:谁在调用它,输入从哪里来,失败后谁负责恢复,数据或状态会不会被重复处理。
- 测试的目标不是追求覆盖率数字,而是用较低成本锁住关键行为和风险边界。
- 单元测试、集成测试和 E2E 测试应该分工明确,越靠近 UI 越要少而关键。
- 高质量测试要避免依赖真实时间、随机数据、网络波动和外部服务状态。
在真实项目中,可以把它当成一个判断框架:先确认输入、约束、失败场景和可观测性,再决定具体工具或写法。 如果一个方案看起来很简单,要继续追问它在规模扩大、权限变化、异常恢复和团队协作下是否仍然成立。
实践检查清单
- 明确这个知识点在系统中的位置:是开发时约束、运行时能力、基础设施能力,还是协作流程。
- 写出一个最小可运行例子,并补一个失败例子;只会写 happy path 说明理解还不够稳。
- 记录常见误用:例如边界条件、权限假设、性能假设、同步/异步差异或环境差异。
- 把概念和项目经历关联起来:如果面试被追问,可以用自己的项目说明为什么这样选。
- 最后用一句话总结取舍:它牺牲了什么,换来了什么。
自测问题
- 这个主题解决的核心问题是什么?
- 如果不用当前方案,还有哪些替代方案?代价是什么?
- 最容易出错的边界条件在哪里?
- 如何在代码、测试或监控中验证它真的可靠?
项目化应用场景
可以把这类知识放到一个登录或订单接口里理解:单元测试验证纯函数和边界条件,集成测试验证 API 与数据库交互,E2E 测试验证用户关键路径。Mock 应该隔离外部依赖,而不是掩盖真实行为。测试越靠近 UI,成本越高、速度越慢,所以应该覆盖最关键路径,而不是把所有细节都塞进 E2E。
常见误区:
- 只测成功路径,不测错误路径。
- Mock 过多导致测试和真实系统脱节。
- E2E 测试依赖真实时间或不稳定外部服务。