ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

sinon spy.threw 详解:检测 spy / fake / stub 是否抛出了异常

sinon spy.threw 详解:检测 spy / fake / stub 是否抛出了异常 测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载spy.threw是 Sinon 中用于判断被观测函数fake、spy或stub在历史调用中是否至少抛出过一次异常的查询方法。它在异常路径断言、错误处理逻辑测试和 mock 校验场景中高频使用既可以无参判断是否抛过异常也可以传入异常类型精确匹配是否抛过指定类型的异常。读完本文你将掌握spy.threw的完整语义、类型匹配规则、底层实现原理以及通过resetHistory/sinon.resetHistory/sinon.reset三种方式重置其状态的实战方法。基本用法spy.threw()当被观测的fake、spy或stub在任意一次调用中抛出了异常exceptionspy.threw()返回true反之返回false。const f sinon.fake.throws(new Error(oh dear)); try { f(); } catch (e) { // 预期会抛出这里吞掉异常以便继续断言 } // f 抛过异常threw() 返回 true f.threw(); // true对应仓库文档 spies/api/threw.md 中嵌入的测试用例 threw-1.test.js 完整演示了这一行为先用sinon.fake.throws构造一个调用即抛出Error的 fake实际调用后在try/catch中吞掉异常再断言f.threw()为真。无参语义的底层实现threw是代理对象proxy上通过delegateToCalls委托给每一次调用记录call object的查询方法其定义位于 src/sinon/proxy.js#L240-L241delegateToCalls(proxyApi, threw, true); delegateToCalls(proxyApi, alwaysThrew, false, threw);其中第二个参数matchAny true表示只要任意一次调用满足条件即返回true与alwaysThrew的所有调用都满足语义相对。委托机制见 src/sinon/proxy-call-util.js#L56-L94当代理从未被调用时直接返回false否则遍历每一次调用调用 call object 上的threw方法并累积结果。每次调用记录上的threw(error)实现位于 src/sinon/proxy-call.js#L91-L97threw: function threw(error) { if (typeof error undefined || !this.exception) { return Boolean(this.exception); } return this.exception error || this.exception.name error; }无参调用时逻辑等价于Boolean(this.exception)——只要该次调用捕获到了异常对象即为true。异常对象是在调用执行期间由代理记录到this.exception上的。按类型匹配spy.threw(TypeError)传入字符串类型的异常名称时spy.threw(TypeError)返回true的条件是被观测函数至少一次抛出了该指定类型的异常。const f sinon.fake.throws(new TypeError(a specific error)); try { f(); } catch (e) { // 预期会抛出 } f.threw(TypeError); // true f.threw(ArgumentError); // false对应文档中的测试用例 threw-2.test.js 精确验证了这一点fake 抛出TypeError后f.threw(TypeError)为true而查询未抛出的ArgumentError类型则返回false。类型匹配的判定规则从 src/sinon/proxy-call.js#L91-L97 的实现可以看到传入参数后匹配采用双轨判定return this.exception error || this.exception.name error;引用相等this.exception error——直接比较异常对象与传入值的引用因此你也可以传入真实的Error实例进行严格匹配类型名相等this.exception.name error——比较异常对象的name属性与传入的字符串。由于内置异常TypeError、RangeError、SyntaxError等的name属性即其类型名传入TypeError这类字符串即可完成类型匹配边界情况当被观测函数某次调用抛出了异常但传入的类型与异常对象引用、name均不相等时返回false。此外若某次调用没有抛出异常!this.exception无论传入什么参数该次调用的threw都会返回false。Resettingthrew到默认状态threw的查询结果建立在历史调用记录之上因此重置历史记录即可将其恢复为默认的false。Sinon 提供三种等价的重置方式重置方式作用范围说明spy.resetHistory()单个 spy / fake / stub清空该对象的调用历史exceptions、args、returnValues等sinon.resetHistory()整个 sandbox 集合对 sandbox 中收集的所有对象批量执行 resetsinon.reset()整个 sandbox 集合先执行 reset含行为重置再执行 resetHistoryconst f sinon.fake.throws(new TypeError(a specific error)); try { f(); } catch (e) { // 预期会抛出 } f.threw(); // true sinon.reset(); f.threw(); // false f.threw(TypeError); // false测试用例 threw-1.test.js 与 threw-2.test.js 均验证了sinon.reset()之后threw()及其带类型版本恢复为false。重置的底层原理resetHistory的核心实现位于 src/sinon/proxy.js#L140-L176。它会把调用历史相关属性全部复位this.exceptions []; this.returnValues []; this.thisValues []; this.args []; this.callIds []; // ... 以及 callCount、called、firstCall 等全部复位threw依赖的异常记录存放在exceptions数组及每次调用的exception字段中清空后自然不再有任何抛过异常的历史。需注意两点禁止在调用过程中重置如果resetHistory在函数仍在执行this.invoking为真时被调用会抛出InvalidResetException见 src/sinon/proxy.js#L141-L148提示Move the call to .resetHistory outside of the callback.级联重置若该 spy 存在withArgs派生出的子 fakeresetHistory会遍历this.fakes并级联重置src/sinon/proxy.js#L169-L173。sandbox 层面的批量重置实现在 src/sinon/sandbox.js#L270-L282sandbox.reset()对集合内每个对象依次调用reset与resetHistorysandbox.resetHistory()则优先调用resetHistory、退化调用reset。相关 API 与进阶阅读spy.alwaysThrew与threw相对要求每一次调用都抛出异常才返回true同样委托自 call object 的threw见 src/sinon/proxy.js#L241文档见 always-threw.mdspy.exceptions属性形式的历史异常数组可直接检查每次调用抛出的异常对象文档见 exceptions.md调用级threw每个 spy call 对象上也有独立的threw可用于细粒度检查某一次具体调用文档见 spy-call/api/threw.md断言中的配套使用assert.threw提供了声明式的异常断言封装见 assertions/api/threw.mdfake 的异常行为配置sinon.fake.throws用于构造调用即抛异常的 fake见 fakes/api/throws.md。小结spy.threw是 Sinon 中判断是否抛过异常的轻量查询方法无参调用判断是否至少抛过一次异常传入异常类型字符串或异常对象引用可做精确类型匹配其底层由 proxy.js 委托至每个 call object 的threw实现proxy-call.js#L91-L97匹配规则为引用相等或name相等二选一。当需要把threw复位时spy.resetHistory()、sinon.resetHistory()、sinon.reset()三种方式均可注意不要在目标函数执行过程中调用重置方法。掌握这些细节你就能在单元测试中精准断言异常路径写出更可靠的错误处理测试。赞分享测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载相关推荐Sinon assert.threw 完全指南断言 fake、spy、stub 抛出异常的权威方法Sinon assert.threw 完全指南断言 fake、spy、stub 抛出异常的权威方法 assert.threw 是 Sinon 内置断言Ass测试开发工具深入解析 Sinon 的 assert.alwaysThrew验证 spy 是否每次都抛出异常深入解析 Sinon 的 assert.alwaysThrew 验证 spy 是否每次都抛出异常 Sinon 是 JavaScript 生态中最常用的测试替身测试开发工具DB-GPT MS-RAG 框架深度指南多源检索增强生成的索引架构与 Agentic 检索实战DB GPT MS RAG 框架深度指南多源检索增强生成的索引架构与 Agentic 检索实战 导读 本文以 DB GPT 官方模块文档 docs/doc测试开发工具上一篇NBTExplorer 完全指南一款免费图形化 NBT 编辑器支持 6 种 Minecraft 数据格式下一篇Burp Suite 完整汉化教程3 步启动 BurpSuiteCN-Release界面一次通过全中文创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表