如何在Vitest和Jest中使用emulate程序化API:createEmulator、reset()与快照完整实战
【免费下载链接】emulateLocal API emulation for CI and no-network sandboxes项目地址https://gitcode.com/gh_mirrors/emul/emulate点击查看免费下载emulate 是一个面向 CI 和无网络沙箱的本地 API 模拟器其程序化 API 可以把 GitHub、Stripe、Vercel、Slack、Google 等十余种服务直接嵌入你的 Vitest 或 Jest 测试中——不是 mock 打桩而是完整有状态的仿真服务让测试代码以为自己打的是真 API。本文将带你完整走一遍createEmulator启动、reset()重置、snapshot()/restore()快照恢复的实战流程。为什么要在测试里用 emulate 程序化 API传统做法是手写 mock每个接口都要手工编造返回值接口一变测试就大面积失效。emulate 的思路完全不同——它在本地启动一个真实行为的 HTTP 服务响应格式、状态持久化、Webhook 签名、OAuth 流程都与生产环境高度一致你的业务代码照常调用官方 SDK只是把地址指向本地端口。在测试场景下它带来三个直接好处✅零外部依赖CI 跑测试不需要任何真实账号、API Key 或网络✅状态完全可控每个用例开始前一键重置回出厂数据✅有状态仿真创建的仓库、订单、消息会真实落库可连续多步断言核心能力都集中在 api.ts 这一个模块里类型定义见 Emulator 接口成员说明url正在运行的服务地址如http://localhost:4001generatedSecrets启动时自动生成的密钥只读reset()清空全部状态并重新灌入种子数据close()关闭 HTTP 服务器返回 Promise30秒上手createEmulator 启动内置服务安装依赖后即可按服务名启动任意内置服务源码位于 packages/emulate/src/import { createEmulator } from emulate const github await createEmulator({ service: github, port: 4001 }) github.url // http://localhost:4001 await github.close()createEmulator支持的常用选项选项默认值作用service必填服务名github、stripe、slack、vercel等 14 种port4000HTTP 端口seed无内联种子数据结构同 YAML 配置文件baseUrl无覆盖对外公布的地址OAuth 回调、Webhook 地址用 小技巧seed让你无需准备emulate.config.yaml测试中直接内联注入用户、仓库、产品等初始数据完整配置示例可参考根目录的 emulate.config.example.yaml。Vitest / Jest 通用装配模板官方推荐的测试装配模式出处见 programmatic-api 文档非常简洁beforeAll里并行启动、afterEach里reset()、afterAll里close()// vitest.setup.tsJest 中放入 jest.setup 文件写法一致 import { createEmulator, type Emulator } from emulate let github: Emulator let vercel: Emulator beforeAll(async () { ;[github, vercel] await Promise.all([ createEmulator({ service: github, port: 4001 }), createEmulator({ service: vercel, port: 4002 }), ]) // 把地址注入环境变量业务 SDK 直接读它 process.env.GITHUB_EMULATOR_URL github.url process.env.VERCEL_EMULATOR_URL vercel.url }) afterEach(() { github.reset(); vercel.reset() }) afterAll(() Promise.all([github.close(), vercel.close()]))Vitest在vitest.config.ts的test.setupFiles中登记该文件即可Jest在jest.config的setupFilesAfterEnv中登记钩子函数同名兼容这套模式的关键思想实例只建一次状态每例必清。reset()让每个用例都从出厂设置开始reset()会清空内存存储并重新执行种子数据测试间互不污染。看一个真实的用例摘自 api.test.tsconst github await createEmulator({ service: github, port: 14020, seed: { github: { users: [{ login: test-user }] } }, }) // 用例A创建一个仓库 await fetch(${github.url}/user/repos, { method: POST, /* ... */ }) github.reset() // 状态清零回到 seed 定义的样子 // 用例B此时仓库列表必然为空断言稳定可重复 const repos await (await fetch(${github.url}/user/repos, { headers: auth })).json() expect(repos).toHaveLength(0)两个值得注意的细节生成的密钥跨 reset 保持稳定。若 GitHub App 省略了private_keycreateEmulator会自动生成 RSA-2048 密钥并放在generatedSecrets中——即使反复reset()密钥不变测试里签发的 JWT 始终有效显式配置的密钥永远不会出现在generatedSecrets里避免密钥泄漏进测试日志快照实战snapshot() 与 restore() 的分工内置服务的状态管理靠reset()就够了但如果你用defineEmulator写了自定义 API比如订单、库存系统emulate 还提供了更细粒度的快照能力。官方示例见 custom-apis 文档const api await createEmulator({ service: counter, listen: false }) const checkpoint api.snapshot() // ① 打快照 await api.request(/increment, { method: POST }) await api.restore(checkpoint) // ② 恢复回快照 await api.reset() // ③ 回到最初种子 await api.close()三者的区别一句话记住操作效果reset()回到最初种子reset 基线snapshot()对当前状态打一份独立副本带格式与版本元数据restore(checkpoint)把当前状态换回快照值但不改变reset 基线⚠️ 快照带有版本保护定义里可以声明stateVersion改了状态结构后不兼容的旧快照会显式报错而不是悄悄恢复出脏数据相关测试见 custom.test.ts。免端口测试listen: false写自定义模拟器测试时还可以完全不占用端口示例项目见 examples/custom-api/const api await createEmulator({ service: inventory, listen: false }) const res await api.request(/reservations, { method: POST }) // 201api.request(path, init)与走 HTTP 共用同一套 handler速度更快、零端口冲突如果你的 SDK 强制要求 URL改用port: 0让系统自动分配端口再读api.url即可。实战演示用 emulate 测 Stripe 支付流程仓库内置的 stripe-checkout 示例 就是这套模式的落地官方stripeSDK 把host指向本地模拟器产品、价格、Checkout Session 全部由seed注入支付完成后还会触发带Stripe-Signature签名的真实 Webhook 流程——全程不花一分钱、不发一个真实请求。测试下单 → 支付 → Webhook 落单链路时典型的断言节奏是afterEach中stripe.reset()保证每个用例看到的是同一批种子产品用api.request或直接fetch创建 Checkout Session断言 Webhook 是否收到checkout.session.completed事件需要多阶段状态时先snapshot()存档失败分支测试完restore()回到分叉点最佳实践清单 端口错开多服务并行启动时各自指定端口如 4001/4002避免默认 4000 冲突实例必须 closeafterAll里统一Promise.all([a.close(), b.close()])否则测试进程可能挂住seed 要完整自定义模拟器的seed是整体替换而非深合并请提供完整状态对象密钥走 generatedSecrets需要自动密钥时省略配置项运行时从实例上读取CI 场景优先 listen: false自定义 API 测试不开端口跑得更快更稳清理放 try/finally单个用例内临时创建的实例用finally { await api.close() }兜底延伸阅读程序化 API 完整选项表programmatic-api/page.mdx自定义 API 生命周期种子、重置、快照、持久化custom-apis/page.mdxcreateEmulator实现与类型packages/emulate/src/api.ts自定义模拟器可运行的完整示例与测试inventory.ts、inventory.test.ts赞分享【免费下载链接】emulateLocal API emulation for CI and no-network sandboxes项目地址https://gitcode.com/gh_mirrors/emul/emulate点击查看免费下载相关推荐使用 emotion/jest 测试 Emotion 样式组件快照序列化器与 toHaveStyleRule 匹配器完整实战使用 emotion/jest 测试 Emotion 样式组件快照序列化器与 toHaveStyleRule 匹配器完整实战 emotion/jest 是前端Linkerd2-proxy架构深度解析从入口流量到出口流量的完整处理流程Linkerd2 proxy架构深度解析从入口流量到出口流量的完整处理流程 Linkerd2 proxy是Linkerd服务网格的专用代理采用Rust编写服务网格网络云原生微服务后端emulate状态持久化实战KV适配器、filePersistence与版本化快照快速上手emulate状态持久化实战KV适配器、filePersistence与版本化快照快速上手 emulate 是一个本地 API 模拟local API em创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

公园道路设计问题:数学建模竞赛中的几何网络优化与Steiner树求解

公园道路设计问题:数学建模竞赛中的几何网络优化与Steiner树求解

简介:这份数学建模论文资源面向参加数学建模竞赛的学生及指导教师,聚焦公园内道路设计的优化问题,要求在任意两入口最短路径不超过直线距离1.4倍的前提下,使道路总长度最小。论文完整给出三个递进问题的建模与求解过程&#xff1a…

2026/10/11 16:08:28 阅读更多 →
攻城掠地sdata文件与本地数据库结构解析及安全修改实操指南

攻城掠地sdata文件与本地数据库结构解析及安全修改实操指南

简介:一份面向攻城掠地游戏玩家、私服架设者及数据库修改初学者的整理版教程,聚焦游戏数据库表结构与sdata文件修改两大核心。文档先系统梳理数据库基本概念、表设计、字段类型、增删改查及权限备份恢复,再逐项解析Gcld数据库常用表&#xff…

2026/10/11 16:08:28 阅读更多 →
ARIMA-BP组合预测:原理、Python实现与避坑指南

ARIMA-BP组合预测:原理、Python实现与避坑指南

简介:结合ARIMA与BP的组合模型完整项目实例,面向具备Python基础、熟悉时间序列分析的研发人员与数据分析师,适用于智能制造、能源负荷、零售销量、供应链库存等高精度预测场景。项目覆盖数据生成、平稳性检验、ARIMA线性建模、BP残差学习与加…

2026/10/11 16:07:27 阅读更多 →

最新新闻

Stable Diffusion 本地部署与显存优化实战:从环境配置到批量出图

Stable Diffusion 本地部署与显存优化实战:从环境配置到批量出图

简介:这份PDF资料面向希望入门AI绘画的开发者与爱好者,系统讲解Stable Diffusion的安装与使用流程,帮助零基础读者跨越环境配置门槛,快速跑通文本生成图像。资源共1个PDF文件,压缩包约814KB,内容以图文步骤…

2026/10/11 17:35:22 阅读更多 →
中医小程序需要哪些功能?从预约到健康管理的完整功能清单

中医小程序需要哪些功能?从预约到健康管理的完整功能清单

1. 引言 随着移动互联网的普及和人们对健康管理需求的提升,中医小程序逐渐成为连接患者与中医师、传播中医文化的重要工具。无论是中医馆、养生馆,还是个人中医师,开发一款功能完善的中医小程序,都能有效提升服务效率和用户体验。…

2026/10/11 17:35:22 阅读更多 →
算力-电力协同:构建数据中心功率动态指纹与可调度性

算力-电力协同:构建数据中心功率动态指纹与可调度性

简介:本资源是腾讯与中国电信联合发布的《数据中心算力-电力灵活性协同研究》白皮书,面向数据中心运维工程师、能源管理从业者、双碳政策研究者及新型电力系统技术开发者。报告聚焦新能源高比例接入背景下数据中心如何通过智能负载调控参与电网需求响应&…

2026/10/11 17:35:22 阅读更多 →
轻量级多任务视觉系统:人脸+疲劳联合检测实战

轻量级多任务视觉系统:人脸+疲劳联合检测实战

简介:本资源是一套完整的Python毕业设计项目,面向计算机、人工智能、自动化等专业学生及初学者,聚焦人脸识别与驾驶员疲劳检测两大核心任务,提供从模型训练到实时预警的端到端实现方案。压缩包共37个文件,含16个可读可…

2026/10/11 17:35:21 阅读更多 →
海康机器人算法SDK与Demo实战:从调用到落地的完整路径

海康机器人算法SDK与Demo实战:从调用到落地的完整路径

简介:本资源为海康机器人VisionMaster算法平台SDK的Demo使用说明文档,面向工业相机视觉应用开发者、机器视觉工程师及自动化项目集成人员,帮助其快速理解SDK核心功能并完成二次开发。压缩包内共1个PDF文件,大小约1.85MB&#xff0…

2026/10/11 17:35:21 阅读更多 →
IP网络基础核心:子网掩码、网关、DNS与网络排障实战

IP网络基础核心:子网掩码、网关、DNS与网络排障实战

干网络这行,不管你是做运维、搞开发,还是转行做物联网、弱电集成,最终都绕不开“IP网络基础”这四个字。很多朋友觉得这玩意儿太简单了,不就是个IP地址嘛,192.168.1.1、子网掩码255.255.255.0,背下来就完事…

2026/10/11 17:34:21 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →