10 本地 Mock 与辅助服务
本地 Mock 与辅助服务解决的是研发链路里最容易被低估的一类问题:邮件发不出去、外部接口不稳定、登录回调没法复现、云资源不能随便创建、网络抖动只能等线上暴露。它们不是生产架构的替代品,而是把外部依赖收进开发机、共享环境和 CI 里,让团队能稳定复现、验证和清理。
替身可信度来自证据链
一个本地服务能启动,只能证明进程存活。可信的依赖替身还要回答四个问题:业务请求是否真的经过它,返回或副作用是否符合当前契约,失败场景能否稳定复现,测试结束后能否恢复到干净状态。
| 替身类型 | 必须保留的证据 | 最容易产生的假阳性 |
|---|---|---|
| 邮件捕获 | SMTP 接收日志、消息 API、收件人与正文断言 | 页面里看到旧邮件,却以为本次发送成功 |
| WireMock | mapping 版本、request journal、未匹配请求 | 宽松匹配吞掉参数或认证错误 |
| MockServer | expectation、times/TTL、verify 结果和活动日志 | 上一用例残留 expectation 命中当前请求 |
| LocalStack | endpoint、初始化钩子、资源查询和真实云差异清单 | 本地 API 成功,却遗漏 IAM、区域和服务配额差异 |
| Keycloak 与 authentik | discovery、issuer、JWKS、redirect URI 和 token claims | 只拿到 token,没有验证签名、受众和回调边界 |
| Toxiproxy | 代理路径、toxic 配置、应用超时/重试指标和恢复结果 | 故障没有经过真实连接,测试仍然绿色 |
端口、命名和凭证要跟第一次启动步骤一起固定。浏览器、宿主机进程、Compose 容器和 CI Runner 看到的地址并不相同;localhost、OIDC issuer、SDK endpoint、SMTP host 和代理 upstream 必须按调用方视角验证。
一次可审计的验证闭环
“容器 up 了”不是验收。邮件必须收到一封测试邮件;HTTP Mock 必须命中一个 stub 并能看到未命中请求;OIDC 必须完成 discovery、JWKS 和 token 校验;LocalStack 必须创建一个对象或队列;Toxiproxy 必须注入一次故障并恢复。
家族选型入口
| 开发现场问题 | 推荐入口 | 判断标准 |
|---|---|---|
| 只需要拦截本地验证码邮件 | Mailpit | 能发、能查、能限制保留上限、UI 不暴露 |
| 历史项目已经依赖 MailHog | MailHog | 继续兼容可以,但要锁版本、限制访问、记录维护风险 |
| 外部 HTTP API 静态响应和录制回放 | WireMock | mapping 文件化、未命中请求可查、stub 有来源 |
| 需要复杂匹配、请求验证和代理 | MockServer | expectation 可初始化、请求可 verify、日志能解释 |
| 本地模拟 AWS 周边服务 | LocalStack | endpoint、假凭证、init hook、auth token 和真实云复核齐全 |
| 本地登录页、OIDC client、回调联调 | Keycloak / authentik | issuer、JWKS、redirect URI、client secret 和测试用户可复现 |
| 模拟依赖延迟、断连、限速 | Toxiproxy | 代理只包住目标依赖,故障注入可撤销 |
长期维护最容易失控的地方
- Mock 规则过期:stub 长期不和真实接口复核,测试越跑越绿,风险越积越厚。
- 状态污染:邮件、request journal、realm、bucket、queue、proxy toxic 都是状态;没有 reset,测试结果就不可解释。
- 地址分裂:浏览器、后端容器、测试脚本看到的 host 不一致,OIDC issuer、回调、CORS、Cookie 和 SDK endpoint 会互相打架。
- 默认账号暴露:邮件 UI、Admin API、Keycloak admin、authentik bootstrap、LocalStack token、MockServer 控制接口都不能随意暴露。
- 录制数据泄露:Authorization、Cookie、JWT、手机号、邮箱、订单号、地址、验证码和重置链接不能进仓库。
- 本地替代真实:LocalStack、WireMock、MockServer 和 Toxiproxy 只能提高验证效率,不能替代真实沙箱、真实云权限和真实网络复核。
推荐项目目录
compose.yaml
.env.example
mail/
wiremock/mappings/
wiremock/__files/
mockserver/initializer.json
localstack/init/ready.d/
keycloak/realm/
authentik/blueprints/
toxiproxy/proxies.json
scripts/verify-local-auxiliary-services.sh
scripts/reset-local-auxiliary-services.sh
docs/dependency-setup.md进入团队模板前,要保证任意新成员能按文档启动服务、跑最小验证、接入项目、清理状态,并知道哪些能力必须回到真实沙箱复核。
