测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载本文以 CHANGES.md 为骨架系统梳理 SinonJavaScript 测试工具库提供 spies、stubs、mocks 与 fake timers从 0.5.0 到 22.0.0 的全部版本变更脉络。读者将了解每个大版本的破坏性变更、核心功能演进ESM 迁移、fake-timers 升级、sandbox 语义修正以及这些变更在 src/ 源码中的落地证据为升级评估与版本选型提供依据。一、变更日志概览文件位置、格式与阅读方法Sinon 的完整变更日志位于仓库根目录的 CHANGES.md共约 2500 行按最新版本在顶部的倒序排列记录了从 2011 年前后的 0.5.0 初始发布到 2026-05-05 发布的 22.0.0 之间所有正式版本含预发布版本的变更条目。日志的条目格式自 12.0.0 起统一由 studio/changes 工具生成对应 2021-11-03 的提交Generate CHANGES.md using studio/changes每条变更包含提交哈希前缀如ed911df5用于追溯具体提交变更标题与作者如Update fake-timers15.4: includes new Temporal API (Carl-Erik Kopseng)版本发布日期以_Released by ... on ..._结尾例如 22.0.0 于 2026-05-05 发布部分条目附带详细说明用引用的段落展开问题的背景、修复思路与影响范围如 22.0.0 中关于子 sandbox 级联恢复回归 #2701 的完整分析。阅读技巧升级时优先关注BREAKING CHANGE、breaking:、chore!:等标记以及每个## X.0.0大版本标题下的条目细节条目中的#XXXX编号对应 GitHub issue可在仓库 issues 中检索上下文。当前仓库的 package.json 声明的版本为22.0.0与日志最新条目一致生产依赖为 sinonjs/commons^3.0.1、sinonjs/fake-timers^15.4.0、sinonjs/samsam^10.0.2与 diff^9.0.0。二、最新版本 22.0.0 详解五个值得关注的内部修复22.0.02026-05-05 发布没有引入面向用户的破坏性 API 变更其核心是依赖升级与一系列影响深远的内部正确性修复这些修复在 src/ 中均有直接对应实现。2.1 fake-timers 升级至 15.4新增 Temporal API 支持Update fake-timers15.4: includes new Temporal API表明本版本的 clock 已能模拟 ECMAScript 的 Temporal 提案 API。在 src/sinon/util/fake-timers.js 中timers导出对象通过addIfDefined条件性地收集setImmediate、clearImmediate、Temporal、performance、requestAnimationFrame、hrtime、nextTick、queueMicrotask等全局能力addIfDefined(timers, Temporal); addIfDefined(timers, performance);addIfDefined只在对应全局存在时才注入源码因此不同运行时环境下sinon.timers的可用成员并不相同——在未提供 Temporal 的 Node 版本中该属性不会被伪造这是兼容旧环境的关键设计。2.2 修复全局可变 callId 在长生命周期进程中无界增长#2691这是 22.0.0 中最具代表性的内部修复。变更说明指出callIdis module-scoped and incremented on every invocation. In long-running test runners or embedded usage, this can grow indefinitely and eventually lose integer precision semantics for strict ordering comparisons.此前 src/sinon/proxy-invoke.js 使用模块级defaultContext { callId: 0 }每次代理函数调用都会执行ctx.callId ctx.callId 1并将该值推入调用记录用于calledBefore/calledAfter等顺序断言。当进程长期运行如 watch 模式、服务端测试宿主时callId会逼近Number.MAX_SAFE_INTEGER失去整数精度从而破坏严格的调用顺序比较语义。22.0.0 的修复实现了回绕wrap-around逻辑见 proxy-invoke.jsconst ctx this.sinonContext || defaultContext; const currentCallId ctx.callId; ctx.callId ctx.callId maxSafeInteger ? 0 : ctx.callId 1;同时sandbox.js 为每个 sandbox 建立独立的sandboxContext { callId: 0 }并通过sinonSpy.withContext、sinonStub.withContext注入见 sandbox.js使并行测试之间的 callId 互相隔离从设计上缓解无界增长与并发干扰问题。2.3 修复sinon.restore()级联恢复子 sandbox 的回归#2701该修复的说明详细复盘了一次典型回归21.1.0 的 ESM 迁移#2683将createSandbox替换为包装函数把每个新建的 sandbox 推入根 sandbox 的 fake 集合createSandbox: function createSandbox(config) { const s createConfiguredSandbox(config); sandbox.getFakes().push(s); return s; }由于子 sandbox 本身也是集合条目Sandbox#restore遍历集合时会对每个条目调用.restore()导致顶层sinon.restore()级联撤销所有子 sandbox 的 stubs/timers——这破坏了子 sandbox 的隔离语义issue #2701且同样的级联也波及resetHistory与verifyAndRestore。22.0.0 恢复 21.1.0 之前的行为根 API 直接持有createConfiguredSandbox的引用见 src/create-sinon-api.js// createSandbox returns an isolated sandbox: its fakes are tracked // on its own collection so consumers can rely on subSandbox.restore() // (and only that) for cleanup. Dont push it into the global sandboxs // collection — doing so caused sinon.restore() to cascade-restore // sub-sandboxes (regression in 21.1.0, see #2701). createSandbox: createConfiguredSandbox,子 sandbox 现在完全隔离只有subSandbox.restore()或verifyAndRestore会清理其 fakes。这是隔离边界语义的重要参考顶层sinon对象本身就是一个 Sandbox自 5.0.1 起sinon即默认 sandbox顶层恢复不会触碰子 sandbox。2.4 修复walk()排除__proto__#2699walk()用于遍历对象原型链以收集待包装的属性是 stub/spy 整个对象时的基础设施。22.0.0 之前walk()会把__proto__当作普通属性处理带来三类问题详见变更说明将__proto__设为对象值会改变对象原型可能让iterator回调感到意外设为非对象值则静默无效seen[k] true不生效Node 以--disable-protothrow启动时读取/写入__proto__会抛出ERR_PROTO_ACCESS。修复后的 src/sinon/util/core/walk.js 在遍历Object.getOwnPropertyNames(obj)时显式跳过__proto__并用Object.create(null)作为seen集合walk.js避免seen自身携带原型属性导致的误判。同时对 getter 属性将目标切换到originalObjwalk.js防止遍历本身触发 getter 副作用。2.5 其它工程化变更Perform additional cleanup when calling callThrough() (#2670)调用callThrough()时执行额外清理Use path.normalize() for path normalization与fix: make build and node test scripts cross-platform构建与测试脚本的跨平台兼容fix: isolate walk state from Object prototype与 2.4 同源的 walk 状态隔离Update to Node 26、Update Ruby gems开发环境的版本升级chore: add context7.json for ownership confirmation仓库根目录新增 context7.jsonimprove GitHub workflows by introducing zizmor for monitoring (#2686)CI 工作流固定 actions 提交哈希、避免凭据泄漏。三、21.x 时代ESM 迁移与 CJS 兼容性工程21.x 系列是整个 Sinon 模块体系重构的高峰期值得单独梳理。3.1 21.1.0全面迁移到 ECMAScript Modules#26832026-04-09 发布的 21.1.0 完成了核心组件的 ESM 迁移。变更说明中的要点This allowed us to finally consume ESM-only dependencies and has broken us free from some CJS shackles. Now produce the same API surface for CJS consumers, as well, by generating./lib.迁移带来了以下工程动作为 CJS 消费者生成./lib目录、新增 distribution 测试装置、锁定 distribution API manifest、对打包产物做冒烟测试、将简单单元测试移到src/、改用并行 mocha 运行 Node 测试等。这一工程结果在 package.json 的入口配置中清晰可见browser: ./lib/sinon.js, main: ./lib/sinon.js, module: ./pkg/sinon-esm.js, exports: { .: { browser: ./pkg/sinon-esm.js, require: ./lib/sinon.js, import: ./pkg/sinon-esm.js }, ./*: ./* }, type: module即CommonJS 消费者走require→lib/sinon.jsESM 消费者走import→pkg/sinon-esm.js浏览器打包器走browser条件。ESM 入口在 src/sinon-esm.js 中只是重新导出 src/sinon.js后者执行createApi()生成默认实例。值得注意的连带修复21.1.1 移除了 ESM-only 的supports-color依赖因为它破坏了 CJS 导出#2692/#269321.1.2 将npm-run-all移到 devDependencies#2694避免下游依赖数量剧增并升级到 ESLint 10 与新的共享配置#2696。3.2 21.0.0移除assert.failException21.0.02025-06-13的唯一变更即为chore!: remove assert.failException property (#2659)标注BREAKING CHANGE。assert.failException是断言失败时抛出的异常类属性在 21.0.1 的文档清理中remove assert.failException from documentation被进一步从文档移除。若你的测试代码曾捕获/断言该属性升级时需改用sinon.assert.fail的自定义失败处理或直接断言抛出的Error。四、20.0.0 与 19.xAPI 瘦身与 fake-timers 换代4.1 20.0.0移除usingPromise与fakeXMLHttpRequest/fakeServer20.0.02025-03-24是一次明确的减负发布chore!: remove usingPromiseusingPromise允许为 stub/mock 指定 Promise 库在 6.2.0 曾为 mock 增加mock.usingPromise。移除理由是Everyone should be using native promises by now, or should know how to stub natives——即原生 Promise 已普及不再需要注入第三方 Promise 实现。chore!: remove fakeXMLHttpRequest and fakeServerBREAKING CHANGEXHR 伪造与 fake server 能力从 Sinon 主包中移除。这两项能力自 3.0.0 起已提取到独立的nise包并重新导入以保持 API 兼容20.0.0 则彻底从 API 面移除。19.0.5 已先行发出弃用警告chore: deprecate useFakeXMLHttpRequest and useFakeServer。需要该能力的项目应直接使用nise。4.2 19.0.0fake-timers 的 Date 子类化19.0.02024-09-13通过upgrade fake timers and others (#2612)引入了一个隐蔽的破坏性变更fake-timers: no longer creating dates using the original Date class, but a subclass (proxy)即伪造的Date不再基于原始Date类而是其子类代理。这对instanceof Date检查是利好——19.0.2 中的Use fix 13.0.2 version of fake-timers to get Date to pass instanceof checks正是为了确保伪造日期能通过instanceof校验。若你的代码对伪造日期做严格的构造器身份判断而非instanceof需要留意此行为差异。4.3 18.0.0Nise 6 与 legacyRoutes 标志18.0.02024-05-15将 Nise 升级到 6.x并启用legacyRoutes标志Use Nise 6 with legacyRoutes flag enabled。变更说明坦诚地指出17.0.2 其实包含两个破坏性变更升级 Nise 后收敛为一个且主要影响sinon-test已同步更新多数用户不受影响。legacyRoutes当前默认启用未来某个版本将默认关闭并发布迁移说明——这是 fake server 路由匹配行为的重要前瞻信号。五、更早的大版本演进16.x 至 0.5.0 的关键节点5.1 16.x~17.x工具链现代化17.0.02023-10-20移除Proxyquireas it did not handle newer syntaxDrop Node 16升级fake-timers11.2.2新增 Intl 镜像与多项 bugfix。16.1.02023-10-05Enable use of assignment in the presence of accessors (#2538)新增复杂环境适配文章暴露 Changelog 页面#2550。16.0.02023-09-13新增.define方法#2539用于在测试期间临时定义新属性——对应 sandbox.js 的sandbox.define(object, property, value)实现它要求属性当前不存在或非自有属性否则抛出Cannot define the already existing property ... Perhaps you meant sandbox.replace()?同时修复 spies 未被正确恢复#2534与injectedKeys未重置#2456等问题。5.2 15.x移除自定义 formatter 与多项行为修正15.0.02022-11-28Fix 2448: remove custom formatter——移除传入自定义 formatter 的选项Sinon 及其子库统一改用 Node 的util.inspect输出人类可读格式与 9.2.3 的Use util.inspect for formatting human readable output (this retires sinonjs/formatio)一脉相承。15.0.2fix throws().callsFake() precedence (#2497)——在已设置 throw 的同一 stub 上无条件调用callsFake()会覆盖先前的 throw 行为与其他 behaviors 的覆盖语义对齐。15.0.4Handling non-configurable object descriptors on the prototype (#2508)——恢复装饰方法decorated methods的可 stub 性#2491。15.1.0Ensure we use a fake-timers version with clock.jump——为clock.jump方法补齐文档#2512对应 docs 中的 jump.md。15.1.1Remove threw(obj) from docs (#2513)——经 12 年无错误报告从文档移除threw(obj)用法。5.3 14.x~12.xNode 版本策略与包结构成型14.0.02022-05-07Drop node 12拥抱 Node 18。13.0.02022-01-28升级 fake-timers 9Fix 2377: Throw error when trying to stub non-configurable or non-writable properties (#2417)Add explicit export for ./* (#2413)。12.0.02021-11-03升级 fake-timers8潜在破坏性但仅涉及伪造 timer 对象多数用户无感Enable esm named exports (#2382)Make calledWith() assertions idempotent (#2407)Generate CHANGES.md using studio/changes本日志的自动化起点。5.4 8.x~11.x兼容性收缩与断言体系完善11.0.0显式使用 samsam 6.0.2修复 #2345警告潜在内存泄漏#2357。10.0.0Use sinonjs/eslint-config4 Adopts ES2017 Drops support for IE 11, Legacy Edge and legacy Safari——ES 目标升级直接导致旧浏览器支持终止。9.0.0Drop Node 8 supportAdd firstArg to spy calls and fakes. (#2150)对应 proxy-call-util.js 的调用记录能力Ignore errors on thisValue property accesses (#2216)。8.0.0移除sinon.spyCall与sinon.sandbox.create升级 nise/sinonjs/formatio/sinonjs/samsam/sinonjs/referee。7.5.0Add sinon.assert.calledOnceWithExactly支持 spy 一个对象的全部方法。7.0.0Update to Lolex 3: no negative ticks allowed——时钟回拨被禁止。5.5 6.x 及以前ESM 起步与 API 现代化6.0.0Export Sinon and its functions as an EcmaScript module (#1809 and #1835)文档化/测试调用顺序检查。5.0.1移除弃用的spy.reset新增sinon.replace、sinon.replaceGetter、sinon.replaceSetter新增fakeUse sinon as a default sandbox——顶层sinon对象自此本身即 Sandbox大多数场景无需再手动sandbox.create()。4.xAdd sandbox.createStubInstance (#1598)、Add match.every and match.some (#1624)(#1661)、新增calledOnceWithExactly断言#1247、弃用spy.reset()改用resetHistory()。3.0.0移除弃用导出Extract fakeXhr, fakeServer and fakeServerWithClock into own module nise and re-import it——fake server 的外置再导入工程。2.0.0允许 stub getters/settersAllow stubbing getters and setters for function properties、新增 getters/setters stub behaviors、Add sinon.addBehavior对应 src/sinon/behavior.js 与 create-sinon-api.js 的addBehavior注入。1.0.0破坏性变更thisObj - thisValue统一调用记录中的 this 命名。0.8.0sinon.wrapMethod no longer accepts faking already faked methods——拒绝二次包装已伪造的方法该语义至今保留在 wrap-method.js 的checkWrappedMethod逻辑中。0.6.0FakeXMLHttpRequest、sinon.useFakeXMLHttpRequest、sinon.fakeServer、sinon.fakeServerWithClock诞生。0.5.0初始发布包含 spies/stubs/mocks、断言、collections/test/testCase 与半成品fake timers。六、源码级对照三大核心机制的当前实现变更日志中的多数条目都能在 src/ 中找到对应实现以下三处是最值得结合阅读的6.1 沙箱与恢复机制sandboxsandbox.js 是 5.0.1sinon 即默认 sandbox、16.0.0.define、22.0.0 子 sandbox 隔离等变更的交汇点。核心机制包括addToCollection维护 fake 集合超过DEFAULT_LEAK_THRESHOLD10000时打印泄漏警告sandbox.js对应 11.0.0 的Warn of potential memory leakssandbox.restore逆序执行 restorer 与集合内restoresandbox.jssandbox.replace/replaceSetter/replaceGetter校验类型一致性、可配置性并登记恢复器sandbox.js拒绝重复替换对应 5.0.5 的Refuse to replace already replaced valuessandbox.define用于临时定义新属性sandbox.js。6.2 属性包装与原型遍历wrap-method / walkwrap-method.js 实现wrapMethod拒绝包装非函数属性、拒绝二次包装已有 wrapper、支持以属性描述符包装对应 2.0.0 的 accessor 支持与 13.0.0 的不可配置属性报错walk.js 实现原型链遍历跳过__proto__22.0.0/#2699、避免触发 getter 副作用对应 17.0.2 的avoid invoking getter as side-effect、用无原型seen集合保证每个属性只遍历一次。6.3 代理调用与调用记录proxy-invokeproxy-invoke.js 是每次 spy/stub/fake 调用的必经之路先通过matchingFakes(args)找到withArgs匹配的兄弟 fake 并同步递增计数、记录thisValues/args/callIds/exceptions/returnValues/errorsWithCallStack再决定走new调用还是普通调用。22.0.0 的 callId 回绕修复proxy-invoke.js与 sandbox 级 callId 隔离sandbox.js就在这里生效支撑calledBefore/calledAfter/callOrder等断言的长跑稳定性。七、升级路径建议与注意事项结合 docs/guides/migration.md 与日志中的破坏性变更从旧版本升级时可按下表核对升级跨度关键破坏点应对21.x → 22.0.0子 sandbox 恢复语义回归修复确认顶层sinon.restore()不再清空子 sandbox子 sandbox 必须自行restore()20.x → 21.x移除assert.failExceptionESM 迁移改用断言错误对象本身验证 CJS/ESM 双入口19.x → 20.0.0移除usingPromise、fakeXMLHttpRequest、fakeServer改用原生 PromiseXHR/fake server 能力迁移到nise17.x → 18.xNise 6legacyRoutes行为关注后续版本对legacyRoutes默认值的调整15.x → 16.x.define语义新属性用define已有属性用replace10.x → 11.xES2017 目标、旧浏览器支持终止评估运行环境Node ≥ 18现代浏览器当前仓库的开发脚本package.json提供了完整的验证手段npm test会依次执行构建、Node 端 mocha 测试、headless 浏览器套件与 webworker 套件npm run test-contract通过 test/distribution 下的 harness 校验打包后的 CJS/ESM 入口行为npm run verify-esm-migration并行运行 lint、契约测试与 Node 测试是 ESM 迁移后防止回归的看门狗。若在升级后运行测试遇到行为差异可先用git log对照 CHANGES.md 中的提交哈希回溯具体变更。赞分享测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载相关推荐CodeIgniter 3.x 官方变更日志深度解读从 3.2.0 到 1.0 的演进路线与源码印证CodeIgniter 3.x 官方变更日志深度解读从 3.2.0 到 1.0 的演进路线与源码印证 导读 本文以官方 changelog.rst https后端Web框架Apache Airflow common.ai 提供商变更日志深度解读0.1.0 到 0.9.0 的演进路线与源码级印证Apache Airflow common.ai 提供商变更日志深度解读0.1.0 到 0.9.0 的演进路线与源码级印证 本文以 common.ai 提供商后端任务调度工作流自动化数据编排批处理数据工程流程编排Apache Airflow Cloudant Provider 变更日志深度解读从 1.0.0 到 4.3.5 的演进路线与升级指南Apache Airflow Cloudant Provider 变更日志深度解读从 1.0.0 到 4.3.5 的演进路线与升级指南 本篇文章以当前仓库中后端任务调度工作流自动化数据编排批处理数据工程流程编排上一篇ruflo-iot-cognitum 的 iot-register 技能实战Cognitum Seed 设备注册、配对与信任初始化完整指南下一篇pydantic.json_schema 模块完全指南Pydantic JSON Schema 生成与自定义 API 深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考