首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
如何用 emulate 的 defineEmulator 编写自己的有状态 HTTP API:自定义模拟器完整教程
📅 2026/10/11 15:21:57
✍️ 爱科研究院
👁 阅读 3,247
【免费下载链接】emulateLocal API emulation for CI and no-network sandboxes项目地址https://gitcode.com/gh_mirrors/emul/emulate点击查看免费下载emulate 是面向 CI 与无网络沙箱的本地 API 模拟API emulation工具内置 14 个生产级有状态服务模拟器借助它的defineEmulator你只需要一个 TypeScript 模块就能编写属于自己的自定义模拟器——一个真正有状态、可重置、可测试的本地 HTTP API。本教程带你从一键脚手架到测试调试完整走通自定义模拟器的编写流程。1️⃣ 为什么自定义模拟器优于传统 mock传统 mock 返回写死的静态响应请求之间互不影响而 emulate 的自定义模拟器是**完全有状态Fully stateful**的每次请求都会真实地读写状态和真实 API 的行为一致。能力静态 mockdefineEmulator 自定义模拟器请求之间共享状态❌✅ 状态由state()管理重置回初始数据❌✅reset()一键回滚浏览器查看请求与状态❌✅ 内置 Inspector/_emulate不开端口跑测试❌✅listen: false进程内直调与 GitHub/Stripe 等内置服务共存❌✅ 同一份配置混合启动2️⃣ 三步快速起步用 init 命令生成 inventory 自定义模拟器在项目里执行下面三条命令一条都不用改就能跑起来npm install -D emulate npx emulate init --custom inventory npx emulate start --watchinit --custom会自动生成三个文件emulators/inventory.ts —— 模拟器定义核心emulators/inventory.test.ts —— 可直接运行的 Node 测试emulate.config.ts —— 服务注册配置脚手架实现的inventory就是一个典型的有状态库存 API初始库存 10 件POST /reservations扣库存并返回 201取消预约归还库存卖光后返回 409。想象一下你在管理下面这类商品start命令会打印服务 URL 和 Inspector 链接端口取决于配置。完整的运行流程可参考 examples/custom-api/README.md。3️⃣ 读懂 defineEmulator三个字段搞定有状态 API自定义模拟器的核心就是defineEmulator的三要素name、state、setupimport { defineEmulator } from emulate export default defineEmulator({ name: counter, // 服务名小写字母、数字、连字符 state: () ({ count: 0 }), // 初始状态工厂每个实例独立 setup({ app, state }) { // 注册路由必须保持同步 app.get(/count, (c) c.json(state)) app.post(/increment, (c) c.json({ count: state.count })) }, })新手需要记住的 4 条规则源码定义见 packages/emulators/core/src/custom.ts可变状态只放进state()不要放在模块级变量里否则reset()无法还原状态必须 JSON 兼容对象、数组、有限数字、字符串、布尔、null日期用字符串表示setup的上下文还提供baseUrl对外宣告的 URL、signal生命周期信号和onDispose清理回调路由支持get/post/put/patch/delete/on/use/onError/notFound响应用c.json、c.text、c.redirect等返回/_emulate是管理保留路径请勿占用。4️⃣ 注册到配置让 CLI 认识你的自定义服务在emulate.config.ts里用defineConfig注册即可自定义服务可以和内置服务混排共存import { defineConfig } from emulate import inventory from ./emulators/inventory.ts export default defineConfig({ services: { inventory: { emulator: inventory, port: 4000 }, // 本地自定义模块 github: { emulator: github, port: 4001 }, // 内置服务 }, })YAML / JSON 配置同样支持emulator可以填本地模块路径或已安装的 npm 包Node 24 可原生加载本地 TypeScript无需额外运行时依赖用npx emulate list查看可用服务--config显式指定配置文件实例名不能占用内置服务名。5️⃣ 种子数据、重置与快照有状态 API 的核心玩法操作行为首次启动以state()结果或seed作为重置基线reset()恢复基线副本并重建所有路由处理器seed整体替换初始状态不是深合并snapshot()/restore()带版本号的分离快照restore不回滚基线持久化可选配置persistence文件后自动存盘如果外部夹具需要校验可在定义里加validateSeed(value)非法种子会直接抛出带路径的错误。修改持久化数据结构时记得递增stateVersion。6️⃣ 不开服务器写测试listen: false 技巧自定义模拟器最大的便利是同一份定义既给 CLI 用也给测试用。listen: false时request()直接走 HTTP 处理器全程不占端口const api await createEmulator({ service: inventory, listen: false }) try { const res await api.request(/reservations, { method: POST }) // 201 console.log(await (await api.request(/inventory)).json()) // { stock: 9 } await api.reset() } finally { await api.close() }api.request走的就是与真实 HTTP 相同的处理器还能验证领域错误如 409 缺货。脚手架生成的 inventory.test.ts 用node --test直接就能跑无需任何测试框架在 Vitest/Jest 中则在 setup 里建实例、afterEach里reset()。SDK 类测试可用port: 0拿到随机端口的真实api.url。7️⃣ Inspector 可视化调试请求与状态一目了然start --watch启动后打开打印出的/_emulate地址即可在浏览器中查看Requests请求记录、Routes路由表、State当前状态并一键 Reset 回初始种子。几个贴心细节access_token、refresh_token、client_secret等敏感字段在预览中自动打码--watch热重载本地模块重载成功后自动重置回种子状态认证头、超大/二进制/流式内容会被省略或摘要不会撑爆面板。8️⃣ 常见问题快速排查清单现象解决方法找不到依赖包包要装在配置文件所在的项目里npx下载的 CLI 不会替你装包发现多个配置文件用--config file显式指定其一种子字段报错提供完整状态对象检查定义里的validateSeed状态重置后仍有残留检查是否误用了模块级变量存放可变状态端口被占用修改该实例的port启动会报告失败并自动关闭已开服务运行时读取的夹具不触发重载把它加进配置的watch路径 延伸资料完整可运行示例含配置与测试examples/custom-api/官方文档页源码apps/web/app/docs/custom-apis/page.mdx自定义 API 技能说明skills/custom-apis/SKILL.mdcreateEmulator程序化 APIpackages/emulate/src/api.ts内置服务总览与 CLI 用法README.md想直接体验完整示例克隆仓库后运行对应示例即可git clone https://gitcode.com/gh_mirrors/emul/emulate从defineEmulator三要素到 Inspector 调试你只需要一个 TypeScript 模块就拥有了和生产行为一致的有状态本地 API——这正是 emulate 不是 mock而是真实状态模拟的核心价值。赞分享【免费下载链接】emulateLocal API emulation for CI and no-network sandboxes项目地址https://gitcode.com/gh_mirrors/emul/emulate点击查看免费下载相关推荐如何编写Browserify自定义转换器面向开发者的完整教程如何编写Browserify自定义转换器面向开发者的完整教程 Browserify是一个强大的JavaScript模块打包工具它通过自定义转换器系统提供了极文档教程老Mac升级macOS免费方案用OpenCore Legacy Patcher五步装上新版系统老Mac升级macOS免费方案用OpenCore Legacy Patcher五步装上新版系统 项目概述 OpenCore Legacy Patcher下文操作系统固件驱动开发如何自己编写缓动曲线easing-functions-cj 中 BaseEasingMethod 自定义动画函数完整教程如何自己编写缓动曲线easing functions cj 中 BaseEasingMethod 自定义动画函数完整教程 做动画时你是否想让曲线按自己的节奏OpenHarmony前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/11 15:21:57
Geant4粒子物理模拟:蒙特卡洛方法与探测器设计实践
2026/10/11 15:21:56
Flutter for OpenHarmony:电子合同签署App性能优化实战
2026/10/11 15:21:56
Flutter在OpenHarmony上的性能调优:手写签名与长列表优化实录
2026/10/11 20:47:30
YOLOv8深基坑变形监测:毫米级位移校准与边缘部署实战
2026/10/11 20:47:30
Spark信用卡评分卡分析:从特征工程到WOE与分数映射
2026/10/11 20:47:30
从自建数据集到部署排查:打电话/抽烟检测的VOC与YOLO全流程实践
2026/10/11 20:47:30
哈工大通信复试不考专业题?真正在考什么
2026/10/11 20:47:30
5G工业互联网PPT怎么写?从场景拆解到业务价值落地的实操方法
2026/10/11 20:42:30
lightweight-charts Brushable Area Series 插件实战:brushRanges 选区样式、交互原语与 Canvas 渲染原理
2026/10/11 0:00:10
流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南
2026/10/11 0:00:10
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别
2026/10/11 0:00:10
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容
2026/10/11 0:00:10
流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南
2026/10/11 0:00:10
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别
2026/10/11 0:00:10
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容
2026/10/11 19:13:46
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/10 3:41:54
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/9 11:36:17
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)