研发协作
用 Vitest 为 TypeScript/JavaScri…
在 TS/JS 项目中需要用 Vitest 编写、运行单元/集成测试并进行 Mock、覆盖率与计时器控制时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
用 Vitest 为 TypeScrip通用
解决思路
- 安装 Vitest:用 Bun 执行 `bun add -d vitest`,或用 npm 执行 `npm install -D vitest`
- 创建 `vitest.config.ts`,用 `defineConfig` 配置 `test`:设 `globals: true`、`environment: 'node'`(或 `'jsdom'`)、`coverage.provider: 'v8'`、`coverage.reporter: ['text','json','html']`、`coverage.thresholds: { lines: 80, functions: 80, branches: 80 }`、`include: ['**/*.{test,spec}.{js,ts,jsx,tsx}']`
- 运行全部测试用 `bun test`;监听模式 `bun test --watch`;CI 单次运行 `bun test --run`;带覆盖率 `bun test --coverage`
- 只跑单个文件:`bun test src/utils/math.test.ts`;按名称过滤:`bun test --grep="calculates sum"`;交互式界面:`bun test --ui`
- 调整输出格式:`bun test --reporter=verbose`(Vitest 2+ 中 verbose 输出扁平列表,需要层级树视图时用 `--reporter=tree`)
- 按基本结构写测试:从 `vitest` 导入 `describe, it, expect, beforeEach, afterEach`,用 `describe` 分组、`it` 写用例,在 `beforeEach` 中做前置准备、`afterEach` 中做清理
- 参数化测试用 `describe.each([{ input, expected }, ...])('名称', ({ input, expected }) => { it(...) })` 批量生成用例
- 断言用法:相等用 `toBe`/`toEqual`;真值用 `toBeTruthy`/`toBeNull`/`toBeDefined`;数值用 `toBeGreaterThan`/`toBeCloseTo`;字符串与数组用 `toMatch(/pattern/)`/`toContain`;对象用 `toHaveProperty`/`toMatchObject`;异常用 `expect(() => throwError()).toThrow('message')`;Promise 用 `await expect(promise).resolves.toBe(value)` 与 `await expect(promise).rejects.toThrow()`
- 函数 Mock:用 `vi.fn()` 创建,配合 `mockReturnValue`、`mockResolvedValue`、`mockImplementation((x) => x * 2)` 设定行为,用 `toHaveBeenCalled()`、`toHaveBeenCalledWith('arg')` 断言调用
- 模块 Mock:用 `vi.mock('./api', () => ({ fetchUser: vi.fn(() => ({ id: 1, name: 'Test User' })) }))`,再正常 `import` 该模块;在 `beforeEach` 中调用 `vi.clearAllMocks()` 清理
- 计时器控制:`beforeEach(() => vi.useFakeTimers())`、`afterEach(() => vi.restoreAllMocks())`,用 `vi.advanceTimersByTime(1000)` 推进 `setTimeout`,用 `vi.setSystemTime(date)` 固定系统时间并断言 `Date.now()`
- 覆盖率操作:`bun test --coverage` 生成报告;`bun test --coverage --coverage.reporter=html` 后用 `open coverage/index.html` 查看 HTML 报告;`bun test --coverage --coverage.thresholds.lines=90` 按阈值校验
- 集成测试用 supertest:`await request(app).post('/api/users').send({ name: 'John' }).expect(201)`,再用 `toMatchObject({ id: expect.any(Number), name: 'John' })` 断言响应体
- 遵循最佳实践:每个源文件对应一个测试文件(`math.ts` → `math.test.ts`);用 `describe()` 分组相关测试;测试名写清楚意图;只 mock 外部依赖;独立的异步测试用 `concurrent`;昂贵 fixture 用 `beforeAll()` 共享;覆盖率目标 80% 以上但不要追求 100%
适用边界 · 注意事项
- 测试非 JavaScript/TypeScript 项目(Vitest 不适用于其他语言栈)
- 需要端到端浏览器测试时改用 Playwright,而不是 Vitest