新闻详情

新闻详情

首页 / 资讯中心 / 详情

Sinon spy.alwaysThrew 完全指南:判断 spy/fake/stub 是否每次调用都抛出异常

发布时间:2026/9/25 2:45:06来源:尧图网络
Sinon spy.alwaysThrew 完全指南:判断 spy/fake/stub 是否每次调用都抛出异常
测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载spy.alwaysThrew是 Sinon 为 spy以及 fake、stub提供的断言式查询方法用于回答一个关键问题被测对象是否在每一次调用中都抛出了异常。与只关心至少抛过一次的spy.threw不同alwaysThrew要求所有历史调用全部抛错才返回true因此非常适合用来验证错误处理路径的稳定性——例如重试逻辑、幂等性测试或任何一次成功调用都算失败的严格场景。阅读本文后你将掌握alwaysThrew的调用形式、异常类型匹配规则、与threw的区别、底层实现原理以及三种重置方式。alwaysThrew是什么根据 官方 API 文档alwaysThrew是一个返回布尔值的方法Returnstrue, when the fake, spy or stub always threw an exception.其适用范围覆盖 Sinon 的三大核心测试替身fake通过sinon.fake创建spy通过sinon.spy或sinon.spy(object, method)创建stub通过sinon.stub创建也就是说只要对象具备 Sinon 代理proxy能力spy.alwaysThrew就可用其行为在三种替身间完全一致。与spy.threw的区别方法语义判定条件spy.threw()至少抛过一次异常任一调用抛出异常即返回truespy.alwaysThrew()每次都抛出了异常所有调用都抛出异常才返回true用一句话记忆threw是存在性判断matchAny truealwaysThrew是全称性判断matchAny false。如果 spy 只被调用过一次两者结果相同一旦 spy 被调用多次只有每次都抛错时alwaysThrew才为true。基本用法最简单的形式是不传任何参数直接判断 spy 是否逢调必抛const f sinon.fake.throws(new Error(oh dear)); try { f(); } catch (e) { // 捕获异常让调用正常记账 } try { f(); } catch (e) { // 第二次调用同样抛错 } console.log(f.alwaysThrew()); // true注意被sinon.fake.throws包装的函数每次调用都会抛出异常因此在测试代码中调用它时必须用try/catch或测试框架的assert.throws之类断言包裹否则异常会直接中断测试进程。这一点在 文档配套测试用例 中有明确示范。混合场景并非每次抛错时返回falsealwaysThrew的命名强调always所以只要出现过一次正常返回就立刻失效let callCount 0; const spy sinon.spy(function () { callCount 1; if (callCount 1) { throw new Error(第一次调用抛错); } // 第二次调用正常返回 }); try { spy(); } catch (e) { // 第一次抛错 } spy(); // 第二次正常返回 console.log(spy.alwaysThrew()); // false因为第二次没有抛错这一行为对应源码测试 spy-test.js 中的用例 returns false if some calls did not throw。spy 一次都没被调用时当 spy 从未被调用时alwaysThrew()返回false见 spy-test.js。这与delegateToCalls的默认逻辑一致——没有调用记录自然谈不上每次调用都抛错。按异常类型匹配alwaysThrew(TypeError)alwaysThrew支持传入一个参数用于限定异常类型只有当每一次调用抛出的异常都匹配该类型时才返回trueconst f sinon.fake.throws(new TypeError(a specific error)); try { f(); } catch (e) { // 捕获 } try { f(); } catch (e) { // 捕获 } f.alwaysThrew(TypeError); // true每次抛的都是 TypeError f.alwaysThrew(ArgumentError); // false类型不匹配从源码看类型匹配的实现位于 proxy-call.js 的threw方法threw: function threw(error) { if (typeof error undefined || !this.exception) { return Boolean(this.exception); } return this.exception error || this.exception.name error; },匹配规则有两条路径对象引用相等this.exception error——传入的实参对象与调用实际抛出的异常对象是同一个引用错误类型名相等this.exception.name error——传入字符串与error.name属性一致例如TypeError、RangeError、Error。因此你可以传入具体的异常实例也可以传入构造器名字符串。注意第二条规则是按name精确匹配的抛TypeError的 spyalwaysThrew(Error)会返回false见 spy-test.js因为TypeError.name TypeError而非Error。传参形式的语义是每次调用的异常都匹配该类型。也就是说即使每次抛出的异常实例不同只要name一致alwaysThrew(TypeError)仍为true。断言辅助assert.alwaysThrew除了在 spy 上直接调用Sinon 的断言模块还提供了对应的辅助方法assert.alwaysThrew(spy[, exception])失败时抛出带语义化消息的异常。其实现位于 assert.jsmirrorPropAsAssertion(alwaysThrew, %n did not always throw exception%C);使用示例const spy sinon.spy(function () { throw new Error(boom); }); try { spy(); } catch (e) { // 捕获 } sinon.assert.alwaysThrew(spy); // 通过 sinon.assert.alwaysThrew(spy, TypeError); // 失败抛出断言异常失败信息模板中的%n会被替换为 spy 的名称%C会被替换为调用上下文信息方便快速定位是哪个替身、哪次调用出了问题。底层实现原理alwaysThrew并不是一个独立手写的函数而是通过 Sinon 的delegateToCalls机制自动生成的。在 proxy.js 中有这样两行声明delegateToCalls(proxyApi, threw, true); delegateToCalls(proxyApi, alwaysThrew, false, threw);这里的关键是delegateToCalls的第二个参数matchAnythrew使用matchAny true任一调用满足条件即返回truealwaysThrew使用matchAny false并把实际委托方法指向threw所有调用都必须满足才返回true。delegateToCalls的完整逻辑在 proxy-call-util.jsproxy[method] function () { if (!this.called) { // 从未被调用默认返回 false除非提供了 notCalled 回调 return false; } // ...遍历所有调用 for (let i 0, l this.callCount; i l; i 1) { currentCall this.getCall(i); const returnValue currentCall[actual || method].apply( currentCall, arguments, ); if (returnValue) { matches 1; if (matchAny) { return true; // threw一有匹配立即返回 } } } return matches this.callCount; // alwaysThrew必须全部匹配 };所以alwaysThrew()的求值过程可以概括为对 spy 的每一次调用call 对象分别执行threw(...)统计匹配次数若匹配次数等于总调用次数则返回true。这就是every-call语义在实现层面的体现。一个值得注意的边界行为如果 spy从未被调用delegateToCalls会直接返回false源码 proxy-call-util.js因此alwaysThrew对零调用场景的答案是确定的false不会出现空真vacuous truth式的歧义。将alwaysThrew重置为默认值alwaysThrew的值取决于 spy 的历史调用记录因此清除调用历史即可将其复位为默认的false。官方文档给出了三种等价途径实例级spy.resetHistory()——只重置这一个 spy 的历史记录保留替身本身全局级sinon.resetHistory()——重置所有已创建的 spy/stub 的历史记录全局级sinon.reset()——更彻底同时重置历史记录与行为behavior。示例与 文档测试 中的复位断言对应const f sinon.fake.throws(new Error(oh dear)); try { f(); } catch (e) { // 捕获 } console.log(f.alwaysThrew()); // true sinon.reset(); console.log(f.alwaysThrew()); // false历史已清空在测试框架如 Mocha、Jest、tap中通常把sinon.reset()或sinon.resetHistory()放进afterEach/beforeEach钩子保证每个用例之间互不污染。实战场景示例场景一验证错误处理分支稳定抛错假设被测函数unreliableApi在特定配置下应当始终失败可以用alwaysThrew直接断言const stub sinon.stub(api, call).throws(new RangeError(out of range)); // 触发多次调用每次都被业务层捕获 for (let i 0; i 3; i) { try { api.call(); } catch (e) { // 业务层已处理 } } stub.alwaysThrew(RangeError); // true场景二区分至少失败一次与每次都失败回归测试中常需要区分两类 bug偶发失败threw为true与必然失败alwaysThrew为true。对偶发问题的修复验证可用threw确认问题出现过对接口完全不工作的阻断性问题则必须用alwaysThrew确认没有任何一次调用成功过。场景三与assert断言配合的失败信息在 CI 中sinon.assert.alwaysThrew(spy, TypeError)失败时抛出的异常会带上 spy 名称与调用上下文%n did not always throw exception%C比裸写if (!spy.alwaysThrew()) throw ...更便于定位问题。小结spy.alwaysThrew()返回true当且仅当 spy/fake/stub每一次调用都抛出了异常适用于 fake、spy、stub 三类替身无参形式判断是否逢调必抛传参形式alwaysThrew(TypeError)或传异常实例判断每次抛出的异常是否都匹配指定类型与spy.threw的区别在于全称量化语义实现上由 proxy.js 的delegateToCalls(proxyApi, alwaysThrew, false, threw)保证类型匹配基于异常对象引用或error.name字符串精确匹配见 proxy-call.js从未被调用的 spy 返回false通过spy.resetHistory、sinon.resetHistory或sinon.reset三种方式复位为默认值断言辅助函数sinon.assert.alwaysThrew提供带上下文信息的失败消息见 assert.js。延伸阅读与alwaysThrew配套的always系列还包括spy.alwaysCalledOn、spy.alwaysCalledWith、spy.alwaysCalledWithExactly、spy.alwaysCalledWithMatch与spy.alwaysReturned它们共享相同的delegateToCalls全称量化机制只是委托的具体 call 方法不同。赞分享测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载相关推荐深入解析 Sinon 的 assert.alwaysThrew验证 spy 是否每次都抛出异常深入解析 Sinon 的 assert.alwaysThrew 验证 spy 是否每次都抛出异常 Sinon 是 JavaScript 生态中最常用的测试替身测试开发工具Sinon assert.threw 完全指南断言 fake、spy、stub 抛出异常的权威方法Sinon assert.threw 完全指南断言 fake、spy、stub 抛出异常的权威方法 assert.threw 是 Sinon 内置断言Ass测试开发工具Sinon assert.alwaysCalledWithExactly校验 fake/spy/stub 每次调用参数都完全一致Sinon assert.alwaysCalledWithExactly 校验 fake/spy/stub 每次调用参数都完全一致 导读 assert.alw测试开发工具上一篇sealed-secrets控制器资源限制防止资源滥用的配置下一篇在 Neovim 中接入 DeepSeekminuet-ai.nvim 智能代码补全配置实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

wx_channels_download v260110 更新解析:公众号 RSS、视频号分页接口与 /play 流代理播放 2026/9/25 3:59:22

wx_channels_download v260110 更新解析:公众号 RSS、视频号分页接口与 /play 流代理播放

桌面应用视频网络MCP 服务 【免费下载链接】wx_channels_download 微信视频号下载器 项目地址: https://gitcode.com/gh_mirrors/wx/wx_channels_download 点击查看 免费下载 导读 本文围绕微信视频号下载器 wx_channels_download 的 v260110 版本发布说明展开&am…

阅读更多 →
AtlasOS 显卡性能优化指南:从自查到一键回退,平均提升 25% GPU 调优方案 2026/9/25 3:59:22

AtlasOS 显卡性能优化指南:从自查到一键回退,平均提升 25% GPU 调优方案

AtlasOS 显卡性能优化指南:从自查到一键回退,平均提升 25% GPU 调优方案 【免费下载链接】Atlas 🚀 An open and lightweight modification to Windows, designed to optimize performance, privacy and usability. 项目地址: https://gitc…

阅读更多 →
老 Mac 免费装新 macOS:OCLP 实战笔记 2026/9/25 3:59:22

老 Mac 免费装新 macOS:OCLP 实战笔记

老 Mac 免费装新 macOS:OCLP 实战笔记 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher(OCLP)是一…

阅读更多 →
ESP32 -O2优化崩溃排查指南:volatile、内存对齐与竞态实战 2026/9/25 3:59:22

ESP32 -O2优化崩溃排查指南:volatile、内存对齐与竞态实战

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

阅读更多 →
使用 ANTLR4 解析 RCS 版本文件:grammars-v4 中 RCS 语法的结构、词法与实战指南 2026/9/25 3:59:16

使用 ANTLR4 解析 RCS 版本文件:grammars-v4 中 RCS 语法的结构、词法与实战指南

编程语言编译器开发工具 【免费下载链接】grammars-v4 Grammars written for ANTLR v4; expectation that the grammars are free of actions. 项目地址: https://gitcode.com/gh_mirrors/gr/grammars-v4 点击查看 免费下载 本篇技术指南围绕 grammars-v4 仓库中的…

阅读更多 →
The Concise TypeScript Book 精读:对象类型(Object Types)的三种定义方式与工程化实战 2026/9/25 3:59:16

The Concise TypeScript Book 精读:对象类型(Object Types)的三种定义方式与工程化实战

文档教程 【免费下载链接】typescript-book The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source. 项目地址: https://gitcode.com/gh_mirrors/typ/typescript-book 点击查看 免费下载 对象类型&#xff…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉