柳嘉希

硕士研究生毕业生

软件工程师 | 可扩展的API · 网络爬虫 · 数据集成 · Vibe代码清理专家

Jest 与 Supertest 复习:单元测试、Mock、异步断言和 API 集成测试

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();

异步测试一定要 returnawait 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 测试重点不是只看状态码,还要断言响应结构、错误分支、权限和边界输入。