[ PROMPT_NODE_25576 ]
testing-anti-patterns
[ SKILL_DOCUMENTATION ]
# 测试反模式
**在以下情况加载此参考:** 编写或更改测试、添加 Mock,或想要在生产代码中添加仅用于测试的方法时。
## 概述
测试必须验证真实行为,而不是 Mock 行为。Mock 是隔离的手段,而不是被测试的对象。
**核心原则:** 测试代码做了什么,而不是 Mock 做了什么。
**遵循严格的 TDD 可以防止这些反模式。**
## 铁律
1. 永远不要测试 Mock 行为
2. 永远不要在生产类中添加仅用于测试的方法
3. 永远不要在不了解依赖关系的情况下使用 Mock
## 反模式 1:测试 Mock 行为
**违规示例:**
typescript
// ❌ 错误:测试 Mock 是否存在
test('渲染侧边栏', () => {
render();
expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
});
**为什么这是错误的:**
- 你在验证 Mock 是否工作,而不是组件是否工作
- 当 Mock 存在时测试通过,不存在时失败
- 对真实行为没有任何说明
**你的人类伙伴的纠正:** “我们是在测试 Mock 的行为吗?”
**修复方法:**
typescript
// ✅ 正确:测试真实组件或不 Mock 它
test('渲染侧边栏', () => {
render(); // 不要 Mock 侧边栏
expect(screen.getByRole('navigation')).toBeInTheDocument();
});
// 或者如果侧边栏必须被 Mock 以进行隔离:
// 不要断言 Mock - 测试 Page 在侧边栏存在时的行为
### 门控函数
在对任何 Mock 元素进行断言之前:
询问:“我是在测试真实的组件行为,还是仅仅在测试 Mock 的存在?”
如果是在测试 Mock 的存在:
停止 - 删除断言或取消对组件的 Mock
改为测试真实行为
## 反模式 2:生产代码中的测试专用方法
**违规示例:**
typescript
// ❌ 错误:destroy() 仅在测试中使用
class Session {
async destroy() { // 看起来像生产 API!
await this._workspaceManager?.destroyWorkspace(this.id);
// ... 清理
}
}
// 在测试中
afterEach(() => session.destroy());
**为什么这是错误的:**
- 生产类被仅用于测试的代码污染
- 如果在生产中被意外调用会很危险
- 违反了 YAGNI 原则和关注点分离
- 将对象生命周期与实体生命周期混淆
**修复方法:**
typescript
// ✅ 正确:测试工具处理测试清理
// Session 没有 destroy() - 它在生产中是无状态的
// 在 test-utils/ 中
export async function cleanupSession(session: Session) {
const workspace = session.getWorkspaceInfo();
if (workspace) {
await workspaceMana