描述在 grunt 中录制与回放 HTTP 场景的方案
解读
面试官想知道:
- 你是否理解“录制 HTTP 场景”=把浏览器/CLI 发出的请求与响应完整持久化;
- 你是否能用 Grunt 插件把持久化后的流量无侵入地回放到本地或 CI 环境;
- 你是否能处理国内常见的HTTPS 证书、跨域、登录态、数据脱敏等工程卡点;
- 你是否能把这套流程与前端构建管线(打包、测试、部署)无缝衔接,而不是“跑个脚本就完事”。
一句话:不是“会不会用某个工具”,而是“能不能用 Grunt 生态给出可落地、可维护、可集成的完整方案”。
知识点
- Grunt 任务生命周期:init → config → registerTask → run;
- grunt-contrib-connect 或 grunt-http-server 起本地桩服务;
- grunt-middleware-proxy 或 grunt-connect-proxy 做反向代理,在本地端口与目标域名之间插桩;
- VCR/录制原理:代理层拦截 req/res → 序列化(HTTP 报文 + 顺序 + 时间戳)→ 落地到 fixtures(JSON/har);
- 回放原理:fixtures 反序列化 → 按顺序返回对应状态码、Header、Body;
- 国内 HTTPS 场景:需用 node-forge 或 mkcert 生成本地 CA,让 Grunt 任务自动注入系统信任库,避免“自签证书报错”;
- 登录态/Token 刷新:录制时把 Cookie/JWT 放到环境变量,回放时用 grunt-template 做占位符替换,实现“数据脱敏 + 多环境复用”;
- 增量更新:grunt-newer 比对 fixtures 时间戳,只重新录制变更接口,降低 CI 时长;
- 与测试框架打通:grunt-mocha-test 在跑单元/E2E 前,先启动“回放模式”桩服务,保证测试用例零网络依赖;
- 性能基线:用 grunt-metrics 统计回放阶段 CPU/内存,防止“桩服务越来越胖”。
答案
我给过一个在某头部电商金融团队落地的方案,核心三步:录制、回放、集成。
第一步,录制。
- 本地开发机安装公司内网根证书,用 grunt-contrib-connect 起 127.0.0.1:8989,并挂载 grunt-connect-proxy,把
/api/*全部转发到真实线上域名; - 代理中间件我用自研的 grunt-interceptor,基于
http-middleware-vcr,把请求方法+路径+MD5(排序后 query) 作为 key,响应码+Header+Body 作为 value,落盘到test/fixtures/vcr/${key}.json; - 对涉敏字段(如手机号、身份证)用 grunt-replace 做正则脱敏,统一替换成
{{faker}}占位符,避免合规风险; - 录制任务注册为
grunt.registerTask('record', ['env:online', 'connect:record', 'interceptor:record', 'watch:record']),开发同学改完代码后,一键npm run record,边点点页面边生成 fixtures。
第二步,回放。
- 新建
connect:playback任务,关闭代理转发,改用 grunt-vcr-playback 中间件,优先读 fixtures,缺失时再 404,保证“无网也能跑”; - 对需要动态延迟的接口,在 fixtures 里加
_delay字段,中间件用setTimeout模拟真实 RT,避免用例因“桩太快”而误报; - 回放任务注册为
grunt.registerTask('playback', ['env:mock', 'connect:playback', 'mochaTest:unit']),CI 里直接npm run playback,平均比真实环境节省 70% 时间,且零外部依赖; - 上线前做“双跑”:同一批用例分别在 playback 与线上环境各跑一遍,对比覆盖率与错误数,差异>1% 就阻断流水线,防止“桩与真值漂移”。
第三步,持续集成。
- fixtures 随代码进 Git LFS,避免仓库膨胀;
- 每周定时
grunt record --reflesh=1,只重录最近 7 天有变更的接口,用 grunt-newer 做增量; - 在 GitLab CI 里加 quality-gate:若 fixtures 新增文件>20 个或单文件>500 KB,自动@接口负责人评审,防止“无脑录一堆垃圾流量”;
- 把回放报告(PVT 格式)上传到内部 Allure 平台,测试、后端、安全三方共视,实现“左移”。
落地效果:
- 开发阶段零等待,后端接口未 ready 时,前端 100% 用桩并行;
- 单元+E2E 总计 2800+ 用例,CI 时长从 45 min 降到 12 min;
- 生产事故率半年下降 35%,因为“双跑”提前发现 11 起契约不一致问题。
拓展思考
- 多环境契约一致性:如何把录制/回放与 Swagger/OpenAPI 契约测试结合,用 Grunt 任务自动生成 “契约- fixtures” 差异报告?
- 流量染色:在录制阶段给请求头注入 X-Mock-Tag=gray,回放时按染色路由到不同桩,实现“同一代码基线同时支持灰度与全量”方案。
- 前端微服务化:当页面由多个独立子应用拼接,如何用 Grunt 做“多端口联合录制”,保证子应用 A 录到的 Cookie 能被 B 实时复用,而不会出现“登录态断层”?
- 性能压测:把 fixtures 导入到 yapi+Artillery,用 Grunt 起任务一键压测,验证“桩服务”本身能否抗住 500 QPS,防止“测试环境没问题,上线就挂”。