mcpField
M
mockable-code

mockable-code

github.com/jpcaparas测试与质量5655 次安装2 天前更新
代码仓库

关于 mockable-code

一项编码技能,指导开发者将外部依赖设计为可替换对象,以便使用测试替身而不扭曲生产代码结构。内容涵盖依赖边界、测试替身选择和可测试性审查。

主要功能

  1. 01分离业务决策与副作用
  2. 02在边界显式声明协作者
  3. 03测试替身选择指南
  4. 04可替换性审查标准与扫描脚本

适用场景

  1. 01编写依赖网络或存储的代码
  2. 02重构包含隐式外部副作用的代码
  3. 03检查测试是否依赖脆弱的交互假设

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jpcaparas/skills --skill mockable-code

安装后在 Claude Code 中输入/mockable-code确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

AGENTS.md
metadata.json
README.md
skill-card.prompt.md
agents/
.gitkeep
assets/
.gitkeep
evals/
evals.json
references/
boundaries.md
gotchas.md
principles.md
review-rubric.md
source-notes.md
test-doubles.md
scripts/
analyze_mockability.py
test_skill.py
validate.py
templates/
mockability-review.md

详细介绍

mockable-code

编写、编辑、重构和审查代码,让依赖项可以替换为 mock、stub、fake 或内存实现,而不会扭曲生产设计。

被动触发

只要任务涉及源代码,且任何行为依赖于协作者、I/O、时间、随机性、持久化、配置、网络调用、队列、SDK、进程状态或框架上下文,就在后台加载此技能。对于微小改动,保持轻量:默默应用核心规则,然后只说明影响最终实现的可 mock 性决策。

决策树

你要做什么?

  • 添加会调用依赖项的代码: 在可行时接受调用方传入依赖项。将领域策略与构造、配置和传输分开。

  • 重构难以测试的代码: 阅读 references/boundaries.md。在更改行为之前,将副作用移到最小且实用的边界之后。

  • 选择测试替身: 阅读 references/test-doubles.md。优先选择能证明行为的功能最少的替身:固定答案用 stub,逼真的内存行为用 fake,交互约定用 mock 或 spy。

  • 审查代码: 使用 references/review-rubric.md。重点指出隐藏的副作用、硬编码的协作者、脆弱的交互测试,以及缺失的约定覆盖。

  • 为其他 Agent 或队友规划工作: 说明依赖边界、要使用的替身、验证命令和停止条件。避免使用“让它可注入”这类模糊建议,而不指出具体依赖及其负责人。

  • 用户要求速度最快,或要制作一次性原型: 保持生产代码简单,但在成本较低时仍应隔离开销大或不可逆的副作用。不要仅为假设中的未来测试构建宽泛的抽象。

快速参考

情况默认操作
直接访问网络、数据库、文件、时钟、随机数、环境变量或队列将其保留在外层边界,或通过小型约定传入
业务规则与 SDK 调用混杂将规则提取为确定性函数,并注入面向 SDK 的适配器
构造函数在内部创建客户端除非本地模式另有要求,否则接受调用方传入的客户端、工厂或配置
静态/全局单例依赖优先在边界处使用显式协作者、上下文对象或窄封装
框架处理程序在处理程序中保留解析和响应格式化;将策略移入可调用的服务/函数
测试需要真实外部服务在访问共享基础设施之前,先使用 fake、stub、约定测试或本地测试容器
接口似乎有用仅当存在真实的替换需求、需要保护的边界,或语言约定要求时才添加
审查发现代码不可 mock指出隐藏的依赖,并展示最小修复路径,不要提出全面重写

核心规则

  1. 将决策与副作用分开。领域策略应能在不依赖真实网络、时钟、文件、数据库、队列或随机性的情况下进行测试。
  2. 在模块、构造函数、函数、处理程序或上下文边界处显式声明协作者。
  3. 优先采用描述调用方需求的窄约定,而非涵盖依赖项所有功能的约定。
  4. 让默认生产接线保持便捷,同时允许测试覆盖协作者,而不必 monkeypatch 全局状态。
  5. 有状态行为使用 fake,固定响应使用 stub,重要交互使用 mock/spy,适配器使用约定测试。
  6. 不要仅为让测试能够访问私有内部实现而将其暴露出来。应将行为移到命名更恰当的单元中。
  7. 不要添加只有假想替代实现的抽象。带有一个明确替换点的简单代码,胜过多层未使用的接口。
  8. 在引入新的测试模式之前,优先遵循本地风格、框架约定和现有测试基础设施。

可模拟性检查

完成代码更改前,请在心中并尽可能使用本地工具运行以下检查:

检查项通过条件
依赖归属读者能够判断每个外部依赖由谁创建、由谁使用
可替换性测试可以替换缓慢、不稳定、成本高或不可逆的协作者,而无需更改生产代码
确定性时间、随机性以及对进程/环境的读取都在边界处受到控制
契约规模接口或协议只包含调用方实际需要的操作
生产环境接线正常运行路径保持简洁、易于追踪
测试意图测试断言行为和重要契约,而非偶然的调用顺序
故障模式可以模拟依赖的错误路径,且不会造成真实副作用
范围此更改提升了可测试性,且没有无关的重写或框架变动

工作流程

  1. 先做侦察。 在设计更改前,阅读附近的构造、依赖注入、测试夹具、模拟和适配器模式。

  2. 找出硬依赖。 列出真实的 I/O、时间、随机性、配置、SDK、数据库、框架和全局状态访问。确定哪些应保留在边界处。

  3. 选择最小的替换点。 使用代码库的常规机制:构造函数参数、函数参数、接口/协议、工厂、上下文对象、模块导入覆盖、夹具或框架提供器。

  4. 实现时避免仅为测试而扭曲代码。 生产代码中的名称应准确。不要仅为了测试而添加 setter、公开的可变字段或宽泛的服务定位器。

  5. 使用有意义的测试替身进行验证。 添加有针对性的测试来替换依赖、覆盖故障路径;如果边界可能发生偏移,至少保留一个适配器或集成测试。

  6. 清楚地报告。 说明更改了哪些依赖边界、使用了哪些测试替身或夹具、运行了哪些命令,以及还存在哪些真实服务风险。

可选辅助工具

使用该辅助工具快速扫描审查提示,而不是将其视为最终结论:

python3 scripts/analyze_mockability.py /path/to/project
python3 scripts/analyze_mockability.py /path/to/project --json

它会标记可能硬编码的副作用和全局变量,供人工或 Agent 检查。扫描结果为空并不能证明代码可模拟,扫描结果嘈杂也不能证明代码有问题。

阅读指南

需求阅读内容
了解默认做法背后的原则references/principles.md
隔离依赖和副作用references/boundaries.md
选择 mock、stub、fake、spy 和契约测试references/test-doubles.md
审查发现和严重程度排序references/review-rubric.md
常见陷阱和反模式references/gotchas.md
来源影响和改编说明references/source-notes.md

注意事项

  1. 可模拟的代码不等于大量使用 mock 的测试。如果行为测试和 fake 能减少脆弱性,请优先使用它们。
  2. 为每个类都创建接口会让代码更难浏览。只有在确实存在替换或归属边界时才添加契约。
  3. 对时钟、随机数生成器、环境变量和全局上下文的隐式读取,往往和网络调用一样容易破坏测试。
  4. Monkeypatching 可能有用,但不应成为替换核心生产代码中协作者的唯一方式。
  5. 如果生产环境接线没有集成测试或契约测试覆盖,依赖注入可能会掩盖构造错误。
  6. 不要为了测试而公开私有方法。应提取真正的策略单元,或通过可观察行为进行测试。

评论

支持 Markdown