应用具备仓库感知能力的 TypeScript 测试设计、行为依据、隔离性与 mock 边界标准。用于编写或评审单元测试时。
Scanned 9/4/2026
Install to Claude Code
npx -y skills add shinpr/ai-coding-project-boilerplate --skill typescript-testing --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Typescript Testing?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/shinpr-typescript-testing-af148e02)More formats (shields.io, HTML) on the badges page.
---
name: typescript-testing
description: 应用具备仓库感知能力的 TypeScript 测试设计、行为依据、隔离性与 mock 边界标准。用于编写或评审单元测试时。
---
# TypeScript 测试规则
## 前置条件检测
在选择测试框架或命令之前,先检查 `package.json`、锁文件、测试配置以及现有测试的导入方式。仅当配置了 Vitest 时才应用 Vitest 专属规则;否则使用仓库已配置的 TypeScript 测试工具,同时保留以下关于行为、隔离性与依据的规则。如果无法确认可运行的测试工具,请报告已检查的路径以及缺失的命令或配置。
## 测试框架
- **Vitest**:当仓库配置或现有测试选用了 Vitest 时使用
- 测试导入:`import { describe, it, expect, beforeEach, vi } from 'vitest'`
- Mock 创建:使用 `vi.mock()`
## 基本测试策略
### 质量要求
- **回归保护**:将测试集中在关键路径、业务逻辑以及一旦回归就会造成实质影响的行为上。当某个未受保护的行为存在实质性回归风险时,添加测试
- **独立性**:每个测试都能独立运行,不依赖其他测试
- **可复现性**:控制时间、随机性、环境变量与外部 I/O,使相同输入产生相同的可观测结果
- **可读性**:每个测试只描述一种行为,将准备/执行/断言分离,并将测试数据限制为该行为实际用到的值
### 测试类型与范围
1. **单元测试**
- 验证单个函数或类的行为
- Mock 所有外部依赖
- 数量最多,采用细粒度实现
2. **集成测试**
- 验证多个组件之间的协作
- 对属于被测行为一部分的进程内真实组件使用真实实现;关于外部 I/O 的处理见“Mock 范围决策”
- 验证实现主要验收标准或跨越进程内组件边界的流程
3. **E2E 测试中的跨功能验证**
- 新增功能时,必须验证其对现有功能的影响
- 对每个集成点进行分级:若失败会破坏主要用户旅程或公开契约则为高优先级,若失败会降低次要可观测行为则为中优先级。需覆盖高优先级与中优先级
- 验证模式:现有功能运行 -> 启用新功能 -> 验证现有功能的连续性
- 成功标准:保留来源验收标准所指定的响应字段与可观测行为;仅当需求或项目配置定义了处理时间阈值的取值与测量方法时,才应用该阈值
- 设计为可在 CI/CD 流水线中自动执行
## 测试实现规范
### 目录结构与命名
- 测试位于被测模块旁的 `__tests__/` 目录中
- 测试文件:`{target-file-name}.test.ts`
- 集成测试文件:`{target-file-name}.int.test.ts`
- 测试套件:描述目标功能或场景的名称
- 测试用例:描述预期行为的名称
### 测试代码质量规则
保持每个已提交的测试处于有效状态。当测试保护的是当前行为时应修复它;只有在其对应行为已不再被要求、且源需求或实现契约确认该行为可移除时,才能删除该测试。
## 测试质量标准
### 边界与错误场景覆盖
在覆盖正常路径的同时,包含边界值与错误场景。
### 字面量预期值
使用与实现计算过程无关的预期值:直接将契约的值写成字面量,或从独立的权威 fixture 或规范中获取。若预期值与被测对象使用相同的常量或公式计算得出,即便两者都错了测试依然会通过。当输入由 mock 提供时,只要实现对输入做了转换,预期值就应与 mock 的返回值不同。
### 基于结果的验证
验证结果,而非调用顺序或调用次数。
### 有意义的断言
每个测试都应断言其使用方所依赖的属性,以及该操作所建立的状态,而不仅仅是断言“有返回值”。
### 能力探测的后置条件
用于检查某项功能是否可用的探测,只有在通过使用方边界进行检查,并断言使用方所需的确切属性时才算通过。
命令的退出状态、成功的导入以及对象的存在性只能说明该事物是可访问的,因此应将它们视为探测的前置条件,而将面向使用方的属性放入断言中。
| 探测意图 | 准备阶段的证据(单独不足以证明) | 应改为断言 |
|---|---|---|
| 模块可用 | `import` 解析成功、`expect(mod).toBeDefined()` | 通过使用方的入口点调用导出的函数,并断言其返回值或产生的效果 |
| 命令可用 | 退出码为 0 | 调用方使用的输出、文件或状态变化 |
| 配置已生效 | 配置文件解析成功 | 该配置本应改变的可观测行为 |
| 迁移已执行 | 命令报告成功 | 通过真实引擎查询返回迁移后的数据结构 |
### Mock 范围决策
对于协作关系正被测试的每个进程内组件,使用真实实现。当测试的目标是更高层的行为时,替换直接的外部 I/O 依赖;当外部适配器、查询、迁移或服务契约本身就是测试目标时,使用真实引擎或与生产环境等效的测试实例。进行替换时,仍需断言被测对象发送的请求以及它所接受的响应结构,以确保边界契约得到验证。
### 基于属性的测试(fast-check)
当设计文档的验收标准带有 Property 标注时,使用 `fc.assert(fc.property(...))` 形式的 fast-check。
## Mock 类型安全强制要求
将 mock 的类型限定为被测对象实际使用的接口部分——即 `Pick<T, 'usedMethod'>`——而非完整接口,这样未被使用的方法即便发生变化也不会破坏测试,而被使用的方法发生变化则会。使用 `satisfies` 针对该 picked 类型约束 mock 对象字面量,使多余或命名错误的属性在编译期就会报错。
## 数据层测试
### Mock 无法验证的内容
Mock 验证的是调用模式,因此以下数据层属性在仅使用 mock 的测试中会被漏检:
- Schema 不匹配(表名、列名、数据类型)
- 查询正确性(join、过滤、聚合、分组)
- 数据库约束(NOT NULL、UNIQUE、外键)
- 迁移兼容性(导致代码与 schema 不同步的 schema 变更)
**判定规则**:当这些属性中的某一项本身就是测试目标——包括仓储层或数据访问实现本身——时,应按照下方的分级方案对真实引擎进行验证。当数据访问只是一个依赖而非测试目标时,使用 mock 是正确的做法:例如接收数据的业务逻辑(mock 仓储层,测试服务层)、错误处理路径(连接失败、超时),以及数据层本身不是测试目标的单元测试。
### 真实数据库测试(依赖环境)
针对真实数据库引擎验证数据层正确性的可选方案:
- **容器化数据库**,用于 CI 环境
- **内存数据库**,用于快速反馈(注意:方言差异可能掩盖问题)
- **专用测试数据库**,配合种子数据
按以下顺序选择第一个符合仓库现有依据的选项:
1. 若存在 CI 已配置的数据库测试工具,则使用它。
2. 否则,若可以执行容器,则在容器中使用相同的数据库引擎。
3. 仅当被验证的行为与方言无关时才使用内存数据库;并记录未被验证的方言相关行为。
4. 若仓库已经预置并隔离了专用测试数据库,则使用它。
当以上都不可用而数据层正确性又是测试目标时,应停止并报告缺失的环境前提条件。仅凭 mock 得出的结果不能作为查询、schema、约束或迁移正确性的依据。
### AI 生成代码与 schema 感知
生成的数据访问代码可能在语法上正确,却引用了并不存在的 schema 元素,而基于 mock 的测试无论如何都会通过。因此设计文档应包含明确的 schema 引用,以便评审时可以将文档记录的 schema 与数据访问代码进行交叉核对。
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!