使用在 Node.js 上运行的 Jest 测试 Workers 是一个优雅的陷阱。测试通过,CI 变绿,代码到达生产环境时带有测试环境永远无法检测到的错误 - 因为测试环境不是在生产环境中运行代码的运行时。 Workers 在 V8 上运行,与 Web 平台 API 隔离,而不是 Node.js API:没有 3、4,5 是运行时的本机实现(不是 6 也不是 7),8 是带有异步签名的 Web Crypto API。在 Node.js 中为 Jest 编写的 9° 模拟可能会通过测试,但当 Worker 处理来自边缘的真实 10° 时,它却默默地无法工作。
为什么测试环境比看起来更重要
Node.js 和 Workers 运行时之间的区别超出了可用的 API:边缘行为仅在特定条件下出现。 Node.js 中的 11 和 Workers 运行时中的 12 具有相同的接口,但它们生成的 13 在传递给 14 操作时可能会有不同的行为,具体取决于版本和实现。 Workers 15 具有与模拟实现不同的标头名称规范化行为(不区分大小写,字典顺序)。
最重要的是:Node.js 中不存在绑定。 16、17、18 是运行时注入的对象 - 无法导入为它们提供完全保真度的 npm 包。手动模拟测试调用模拟的代码,而不是与实际绑定一起使用的代码。
19 通过在真正的 Workers 运行时(特别是 Miniflare v3)中运行测试来解决这个问题,它运行真正的 V8 隔离,而不是 Node.js 模拟。测试可以通过运行时实现访问202122232425。绑定作为进程内实现提供:内存中的 KV、D1 作为嵌入式 SQLite、R2 作为本地存储。结果是,通过 26 的测试正在测试将在实际运行时运行的代码。
使用绑定配置 vitest.config.ts
27 中的工作池配置是您声明测试将接收的绑定的地方。该结构镜像 wrangler.toml,但在 Vitest 配置中:
0
通过此配置,每个测试套件都会收到一个干净的环境,其中包含空的 KV 命名空间、空的 D1 SQLite 数据库(如果配置 28 则具有应用的架构)和空的 R2 存储桶。套件之间的绑定是隔离的——一个套件中的测试所做的更改不会泄漏到另一个套件。
为了访问测试中的绑定,29 导出 Miniflare 通过全局机制注入的帮助程序30:
1
31 是正在测试的 Worker 本身的绑定 — 您可以执行 32 将获取处理程序作为集成 HTTP 调用进行测试,并具有完整的路由和所有可用的绑定。
单元测试和集成测试的划分
对纯 JavaScript 值进行操作的业务逻辑函数(解析 JWT、计算折扣价格、验证输入模式)可以而且应该在没有 Workers 池的情况下进行测试。这些函数不依赖于运行时 API 或绑定,并且使用标准 Vitest 在纯 Node.js 中测试它们更快、更简单。经验法则:如果函数接受并返回 JavaScript 原始值或平面对象,则它属于 Node.js 池。如果它使用 33、34、35、36 或任何绑定,则它属于 Workers 池。
集成 HTTP 处理程序(作为 Worker 入口点的 37 函数)需要对 Worker 池进行忠实测试。测试集成处理程序意味着进入 38 并检查 Worker 在生产中生成的响应的状态、响应标头和正文。此测试对绑定也有副作用:如果处理程序应在 D1 中保存记录,测试可以稍后执行 39 并验证数据是否正确写入。
没有 Cloudflare 凭证的 CI — 以及 Miniflare 的限制
带有 Miniflare 的 40 完全在本地运行 — 不会对 Cloudflare API 进行任何调用,不需要 CI 中的 41 或 42。 Miniflare v3 将 43(Cloudflare 的开源运行时)下载为本地二进制文件,并像任何其他进程一样运行它。 CI 管道可归结为 44 和 45 — 没有秘密,除了首次安装时下载二进制文件之外没有网络依赖性。
Miniflare v3 以高保真度模拟运行时,但有记录的异常情况对测试策略很重要。生产模式下的持久对象(具有全局单例保证)不是用分布式一致性来模拟的; Miniflare 创建一个对基本逻辑有用的本地实例,但不测试实际的协调行为。边缘缓存和具有真实地理位置数据的 46 对象等 CDN 行为需要 47 才能执行。
对于这些情况,答案是进行冒烟测试,在部署后直接对暂存 Worker 进行 HTTP 调用。它们不会取代 Miniflare 测试——它们涵盖了 Miniflare 无法模拟的内容:仅当代码在真实基础设施上运行时才存在的行为。
测试 waitUntil 和后台工作
48是响应发送后发生工作的地方。测试中的49会立即返回答案,但传递给50的工作可能尚未完成。 51提供了52来解决这个问题:
2
如果没有53,检查54副作用的测试将出现竞争条件——难以诊断的脆弱性,因为问题不在生产代码中,而是在测试代码中。
另请阅读
- [生产中的 Cloudflare Workers:hello world 之后发生了什么变化55
- [Workers + D1 + KV + R2:在同一服务中组合绑定56
- [Workers:调试、日志和 Workers Tail — 无需日志服务器即可在边缘进行观察57
- [工人:CPU 和内存限制 - 文档没有很好地解释58
- [2025 年使用 AWS Lambda 和 Cloudflare Workers 开发无服务器应用程序59
- [Cloudflare Workers:无服务器边缘计算实用指南60
