Phase 3 / Ep 16: 外部接口 Mock 极简道

⏱ 预计阅读 4 分钟 更新于 2026/4/13

进入到我们的下一个 task_plan.md 环节:建立我们要发送给 Google 的 API 处理类(API Adapter 层)。

根据之前定下的 “无测试不写码” 铁律。我们要写这个类,就必须先写它的 google_sync.spec.ts。这里就会碰到一个在项目开发里致命的问题:

在自动跑 TDD 那几分钟里,Agent 可能会因为尝试排错,在一分钟内自动把整个测试文件运行 30 遍。如果测试代码里真的写了原始的 fetch('https://www.googleapis.com/') ,你辛辛苦苦申请下来的 Google API Key,会在半路就被谷歌因为限流防火墙规则当成恶意爬虫而封停。

1. 教唆 Agent 掌握谍战替换(Mocking)

我们必须进一步收紧我们的流程描述。当你面对测试时,需要植入这种思想,在 GEMINI.md 或者前两期的 test-driven-development 中补充一个技术细节原则:

“【测试黑盒原则】任何涉及外部 HTTP 请求与外部数据库的 I/O 测试,绝不准发起真实网络动作。必须优先采用 vi.mock / nock 或者同类的函数劫持方法伪造外部沙盒响应。”

2. 模拟一场 Google API 调用

当我们要 Agent 实现提取 Google Calendar 事件函数并测通时,它这次生成的测试(在你的规矩压制下)会变成了这种形态:

import { describe, it, expect, vi } from 'vitest';
import { fetchCalendarEvents } from '../src/google_adapter.ts';

// 致命一步:Agent 听了你的话,它自动劫持了整个基础请求层!
global.fetch = vi.fn(); 

describe('Google Calendar Sync Adapter', () => {
   it('should fetch and map event to local formats', async () => {
       // Agent 伪造了一个谷歌如果正常返回时的数据(Mocking!)
       const mockGoogleResponse = {
           items: [{ id: '123', start: { dateTime: '2026-10-01' } }]
       };
       (fetch as any).mockResolvedValue({
           ok: true,
           json: async () => mockGoogleResponse
       });

       const res = await fetchCalendarEvents('fake_token');
       
       // 它只测试:我们的解析代码,有没有正确把 123 放进了系统结构对象里。
       expect(res).toHaveLength(1);
       expect(res[0].eventId).toBe('123');
   });
});

3. Phase 3 结语

现在你应该感受到了 TDD 与外部 Mock 的巨大威力了吧。你将所有的“外部干扰”全部剪断屏蔽。只要这个 google_adapter 能顺利地跑出绿灯,将来在正式环境连通时,出问题的概率将无限逼近于 0(除非 Google 改了接口字典定义)。

总结 Phase 3 进度: 我们现在不仅有一个能自主产生需求的架构师,更拥有了一位代码不会烂尾的偏执狂程序员(Test-Driven、3 次失败懂得报警、会写断言桩隔离外部通讯)

在即将到来的 Phase 4 中,这台轰鸣的战争机器将开赴前线深水区。我们要与真正的外部实体(由 OAuth 控制的鉴权授权和真实的 webhook 消息池)进行血战!