TypeScript 单元测试
单元测试用最小用例验证单个函数或模块的行为,防止改动引发回归。TypeScript 项目常用 Jest 或 Vitest 做测试框架,测试代码本身也使用 TS 编写,享受类型提示与自动补全。
搭建测试环境
Vitest 与 Vite 同源、开箱支持 TS,安装后配置极简:
npm i -D typescript vitest
package.json 增加脚本,并准备 vitest.config.ts:
{ "scripts": { "test": "vitest run" } }
// vitest.config.ts
import { defineConfig } from "vitest/config";
export default defineConfig({ test: { include: ["test/**/*.test.ts"] } });
编写第一个测试
先写被测模块,再写用例,断言用 expect + 匹配器:
// src/math.ts
export function add(a: number, b: number): number {
return a + b;
}
// test/math.test.ts
import { describe, expect, it } from "vitest";
import { add } from "../src/math";
describe("add 函数", () => {
it("两个正数相加", () => expect(add(1, 2)).toBe(3));
it("支持负数", () => expect(add(-1, 5)).toBe(4));
it("0 参与运算", () => expect(add(0, 0)).toBe(0));
});
运行 npm test,三个用例全部通过即输出绿色结果。
异步测试与 Mock
异步函数直接返回 Promise,测试里用 await;外部依赖(如 fetch)用 vi.fn / vi.stubGlobal 替换:
// src/api.ts
export async function loadUser(id: number): Promise<{ id: number; name: string }> {
const res = await fetch(`/api/user/${id}`);
return res.json();
}
// test/api.test.ts
import { expect, it, vi } from "vitest";
import { loadUser } from "../src/api";
it("按 id 请求用户并返回数据", async () => {
const json = () => Promise.resolve({ id: 1, name: "张三" });
vi.stubGlobal("fetch", vi.fn(() => Promise.resolve({ json })));
const user = await loadUser(1);
expect(user).toEqual({ id: 1, name: "张三" });
});
小结
测试文件与被测文件一一对应,先测小函数、再测异步与 Mock。常用断言有 toBe、toEqual、toThrow 与 toHaveBeenCalled;把 npm test 挂进 CI 后,每次提交都会自动验证类型安全的行为是否仍然成立。