用途:将依赖 unittest.mock.patch / MagicMock 的测试重构为 erk 的 gateway-based fake 模式,即让源码通过注入网关依赖,测试中改为配置预置响应的 fake。触发条件:测试文件从 unittest.mock 导入 patch,或使用 @patch(...) 装饰器。
主要流程:
- 审计 mock 使用:逐个 patch 记录 mock 目标、系统边界(工具)、模拟内容、返回值。同一系统边界的多个 mock 应由单个 gateway 覆盖;一个测试里同时 patch 2-3 个对象,暗示它们应被一个可注入 gateway 覆盖。
- 网关发现:不要把 subprocess.run 当作正确的 gateway 边界;gateway 应按被调用的工具命名(如 GhCli、CmuxGateway、GitGateway),而非按底层机制命名。先定位被测的系统边界(如 shutil.which("claude") 表示检查 Claude CLI 是否安装),再做定向搜索,并优先选择覆盖全部 mock 目标的更高层抽象。
- 规划注入:找到被 patch 的源码中直接调用 mock 对象的位置,判断是否已有构造参数,并规划生产环境接线。
- 使源码可注入:以命名参数方式添加 gateway 构造参数,不设默认值,存为 self._gateway,把直接系统调用替换为 gateway 方法调用,并映射返回类型。对 Click 命令(尤其是 exec scripts)改用 Click context 注入,例如 require_github(ctx)、require_context(ctx).cmux。
- 无合适 gateway 时创建:参考 docs/learned/architecture/gateway-abc-implementation.md,按 3 文件(abc、real、fake)或 5 文件模式创建,完成 ErkContext 接线与错误处理决策。
- 重写测试:移除 patch 导入,构造带预置响应的 fake,通过新构造参数传入,把 mock 断言替换为 fake 属性检查(如 assert len(executor.prompt_calls) == 1)。注意 monkeypatch.delenv 属于 pytest 内置,可保留。
- 验证:运行 uv run pytest <test_file> -v,再对修改的源码做 lint 和类型检查。
适用场景:erk 及 dagster-io/fake-driven-testing 相关代码库中,需要去除 unittest.mock 并改用 fake 的测试重构。限制:资料未提供安装命令、收费信息或具体平台支持;部分内容涉及仓库内部路径与约定,需结合对应代码库使用。