用途
Testing Anti-Patterns 是一份关于测试反模式的实践指南,适用于编写或修改测试、引入 mock,或想给生产代码添加仅供测试使用的方法时参考。其目标很明确:防止把测试写成「测试 mock 行为」,也防止生产代码被测试专用逻辑污染。核心原则是——测试要验证代码做什么,而不是验证 mock 做什么;mock 只是隔离手段,不是被测对象。
主要能力/内容
文档归纳了几类反模式,并给出对照代码与检查项。
铁律
- 永远不要测试 mock 行为。
- 永远不要向生产类添加仅供测试使用的方法。
- 永远不要在不理解依赖的情况下 mock。
反模式 1:测试 mock 行为
违规写法是渲染组件后断言某个 *-mock 的 test id 存在。这样验证的是 mock 是否工作,而不是组件是否工作,测试会在 mock 存在时通过、不存在时失败,无法反映真实行为。修正方式是测试真实组件或取消 mock,例如断言导航语义角色;如果确实需要 mock 以隔离,则不要对 mock 本身做断言。检查项:在对任何 mock 元素断言之前,先问自己是在测真实组件行为还是仅测 mock 是否存在,若是后者就删除断言或取消 mock。
反模式 2:生产代码中的测试专用方法
示例中 Session.destroy() 只在测试的 afterEach 里使用,却看起来像生产 API。问题在于生产类被测试专用代码污染、误在生产调用会有风险、违反 YAGNI 与关注点分离,并混淆对象生命周期与实体生命周期。修正方式是把清理逻辑放进测试工具,例如在 test-utils/ 中提供 cleanupSession。检查项:添加方法前先问「是否只被测试使用」,若是就不要添加;再问「这个类是否拥有该资源的生命周期」,若不是就说明放错了类。
反模式 3:不理解就 mock
示例中 mock 掉了 ToolCatalog 的注册逻辑,而该逻辑带有测试所依赖的副作用(写配置),导致重复添加服务器本应抛错却不会抛。问题在于被 mock 的方法带有测试依赖的副作用,过度 mock 破坏了真实行为,测试可能因错误原因通过或神秘失败。修正方式是 mock 在正确的层级:mock 慢的部分、保留测试所需行为,例如只 mock 服务器启动。检查项:mock 前先停下,问真实方法有哪些副作用、测试是否依赖这些副作用、是否完全理解测试需要什么;若依赖副作用,就 mock 更底层的外部或慢操作,而不是测试依赖的高层方法;不确定时先用真实实现跑一遍测试观察。危险信号包括「为了保险先 mock 一下」「这个可能慢,还是 mock 吧」,以及在不理解依赖链的情况下 mock。
反模式 4:不完整的 mock
示例只构造了 status 与部分 data 字段,缺少下游代码会使用的 metadata。问题在于部分 mock 会掩盖结构假设、下游可能依赖未包含字段而静默失败、测试通过但集成失败、造成虚假信心。铁律是 mock 要按现实中存在的完整数据结构来构造,而不只是当前测试用到的字段。修正方式是补全真实 API 返回的所有字段。检查项:创建 mock 响应前,先确认真实 API 响应包含哪些字段,查阅文档或示例,包含系统下游可能消费的所有字段,并核对 mock 与真实响应 schema 完全一致;不确定时至少包含所有有文档记载的字段。
反模式 5:把集成测试当作事后补做
违规情形是实现完成、没有测试,却说「可以测试了」。问题在于测试是实现的一部分而非可选后续,TDD 本可更早发现,没有测试就不能声称完成。修正方式是走 TDD 循环:先写失败测试、实现使其通过、重构,然后才算完成。
mock 过于复杂的信号
文档列出若干警告信号:mock 搭建比测试逻辑还长、为了让测试通过而 mock 一切、mock 缺少真实组件拥有的方法、mock 一变测试就坏。此时应自问是否真的需要 mock,并用真实组件写集成测试往往比复杂 mock 更简单。
使用方式
这不是可安装的软件包,而是一份通过阅读与自查来使用的规范。它用「Gate Function」形式给出可执行的自检步骤:在断言 mock、添加方法、mock 方法、创建 mock 响应之前,先按问题清单判断并停下。文档还建议用严格 TDD 来预防这些反模式:先写测试会迫使你想清楚在测什么,看着它失败能确认测试测的是真实行为而非 mock,最小实现能避免测试专用方法混入,先接触真实依赖能让你在 mock 前看清测试真正需要什么。如果测试的是 mock 行为,说明违反了 TDD——因为你没有先让测试对着真实代码失败就加了 mock。
适用场景
适用于单元测试与集成测试设计、需要引入 mock 或测试替身、审查测试代码质量、以及判断是否应把清理逻辑从生产类迁出等情形。文档末尾的速查表把反模式与修正一一对应:对 mock 元素断言→测真实组件或取消 mock;生产类中的测试专用方法→移到测试工具;不理解就 mock→先理解依赖再最小化 mock;不完整的 mock→完整镜像真实 API;测试当补做→TDD 测试先行;mock 过度复杂→考虑集成测试。
限制
资料未提供该内容的许可协议、维护者、版本或更新时间信息,也未说明其配套工具、安装命令或运行环境;这些事实暂未提供。