ARTICLE DETAIL

资讯详情

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

sinon.match.func 匹配器指南:在 Sinon 中断言函数类型参数

sinon.match.func 匹配器指南:在 Sinon 中断言函数类型参数 sinon.match.func 匹配器指南在 Sinon 中断言函数类型参数【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址: https://gitcode.com/gh_mirrors/si/sinonsinon.match.func是 Sinon 匹配器Matcher体系中用于校验参数是否为函数的专用匹配器它在 fake/spy/stub 的调用断言中扮演类型守卫角色让你无需关心具体函数实现只需确认这里被传入了一个可调用的函数。读完本文你将掌握sinon.match.func的完整用法、它与sinon.assert.calledWithMatch、spy.withArgs等 API 的组合方式以及它在当前 Sinon 仓库中的底层实现原理与边界行为。一、sinon.match.func是什么根据官方文档 func.md 的定义Requires the value to be aFunction.即要求被校验的值是一个函数Function。当被检查的参数满足该条件时匹配成功否则匹配失败。它是 Sinon 匹配器大家族中的一员。在 Matchers API 索引 中可以看到Sinon 提供了一整套面向不同数据类型的内置匹配器包括array、bool、date、number、object、regexp、string、symbol、typeOf等而func专门负责是否为函数这一类型判定。关于匹配器的整体使用背景可参考 Matchers 介绍匹配器可以被传给spy.calledOn、spy.calledWith、spy.returned及对应的sinon.assert系列函数以及spy.withArgs用于对期望值进行更模糊或更精确的匹配。二、基本用法配合断言 API 使用sinon.match.func最常见的用法是作为断言参数传入。它可与calledWithMatch、alwaysCalledWithMatch等断言 API 组合判断某个调用中指定位置的参数是一个函数。以仓库中的配套测试 func.test.js 为蓝本最直接的示例import * as sinon from sinon; const fake sinon.fake(); fake(function () {}); // 断言 fake 曾被调用且调用参数是一个函数 sinon.assert.calledWithMatch(fake, sinon.match.func);这段代码通过断言sinon.assert.calledWithMatch验证了fake至少被调用过一次且第一次调用传入的参数匹配sinon.match.func即是一个函数。若匹配失败断言会抛出包含expected fake to be called with match的错误信息——该信息模板定义在 assert.js 中mirrorPropAsAssertion( calledWithMatch, expected %n to be called with match %D, );三、完整行为验证接受与拒绝的边界配套测试 func.test.js 用 4 个用例完整刻画了sinon.match.func的判定边界这是最权威的行为证据3.1 接受普通函数声明fake(function () {}); t.doesNotThrow(() { sinon.assert.calledWithMatch(fake, sinon.match.func); }, should accept function);普通函数声明function declaration / 函数表达式通过校验。3.2 接受箭头函数fake(() {}); t.doesNotThrow(() { sinon.assert.calledWithMatch(fake, sinon.match.func); }, should accept arrow function);箭头函数arrow function同样通过校验。由于sinon.match.func的判定基于 JavaScript 的函数类型语义可以推断只要typeof value function的值都会被接受因此async function、generator 函数、classtypeof 亦为function等可调用/可实例化实体在语义上也应能通过匹配。3.3 拒绝带 call 方法的普通对象fake({ call: () {} }); t.throws( () sinon.assert.calledWithMatch(fake, sinon.match.func), /expected fake to be called with match/, should reject object );一个拥有call属性的普通对象不会被误判为函数。这一点非常重要——sinon.match.func校验的是真实的函数类型而非长得像函数的对象。例如{ call: () {} }这类模拟可调用形态的对象会被明确拒绝。这也意味着它比sinon.match.has(call, sinon.match.func)这类针对属性做匹配的方式语义更严格、更直接。3.4 拒绝字符串等非函数值fake(function); t.throws( () sinon.assert.calledWithMatch(fake, sinon.match.func), /expected fake to be called with match/, should reject string );即使是内容为function的字符串也不会通过匹配——匹配器关注的是值的运行时类型而不是字面内容。3.5 行为小结传入值匹配结果依据function () {}✅ 通过测试用例 should accept function() {}✅ 通过测试用例 should accept arrow function{ call: () {} }❌ 拒绝测试用例 should reject objectfunction字符串❌ 拒绝测试用例 should reject string四、更多使用场景4.1 用于 spy 的calledWithMatchsinon.match.func不只适用于 fake也可直接用于 spy 的调用记录查询const spy sinon.spy(); spy(() {}); spy.calledWithMatch(sinon.match.func); // true相关 API 说明可参考 called-with-match.md。4.2 与alwaysCalledWithMatch组合当需要断言每一次调用都传入函数时使用alwaysCalledWithMatchconst spy sinon.spy(); spy(() {}); spy(() {}); sinon.assert.alwaysCalledWithMatch(spy, sinon.match.func);4.3 用于withArgs条件化 stub/fakesinon.match.func还可以配合spy.withArgs/stub.withArgs使用实现当参数是函数时走特定行为的条件逻辑const stub sinon.stub(); stub.withArgs(sinon.match.func).returns(got a function); stub.withArgs(sinon.match.number).returns(got a number); stub(() {}); // got a function stub(42); // got a number4.4 用于 mock 的 expectation在 mock 的expects()期望中同样可以用匹配器约束参数类型const mock sinon.mock(obj); mock.expects(method).withArgs(sinon.match.func);相关文档可参考 expectations.md。五、与sinon.match.typeOf(function)的关系Sinon 还提供更通用的类型匹配器sinon.match.typeOf(type)见 type-of.md。它支持的 type 列表包含undefined、null、boolean、number、string、object、function、array、regexp、date、symbol。因此以下两种写法在语义上等价sinon.match.func sinon.match.typeOf(function)选择建议sinon.match.func写法更简洁、意图更聚焦sinon.match.typeOf(function)则在你需要统一管理多种类型断言、或在配置化场景下动态传入类型字符串时更有优势。六、底层实现原理委托给 sinonjs/samsam从源码看sinon.match并非在 Sinon 内部自行实现而是委托给sinonjs/samsam包。在 create-sinon-api.js 中可以看到 API 组装的关键一行import samsam from sinonjs/samsam; // ... match: samsam.createMatcher,即sinon.match直接指向samsam.createMatcher该依赖声明于 package.json 的sinonjs/samsam: ^10.0.2而sinon.match.func正是createMatcher返回的匹配器对象上提供的具名匹配器之一。匹配器在调用链中的消费方式也清晰可见在 assert.js 中sinon.assert.match(actual, expectation)通过createMatcher(expectation)创建匹配器并调用matcher.test(actual)完成校验在 proxy-call.js 中calledWithMatch对每个期望参数执行match(expectation).test(actual)逐一比对实际调用参数在 spy-formatters.js 中匹配器对象还参与断言失败时的消息格式化通过matcher.message与matcher.test决定如何高亮展示失配参数。由此可以理解sinon.match.func的完整工作路径sinon.match.func是一个带test(value)方法的匹配器对象 → 断言 API 将其与真实参数逐位比对 → 匹配失败时抛出格式化错误消息。这也是所有内置匹配器any、string、number等共享的统一机制。七、常见误区与注意事项不要用含 call 方法的对象冒充函数如测试所示{ call: () {} }会被拒绝。sinon.match.func判定的是真实类型而非形态。它是类型匹配不是内容匹配传入字符串function无法通过如需校验函数名叫什么或函数体内容应改用自定义匹配器参见 custom-matchers.md或callsFake等行为 API。配合calledWithMatch系列而非calledWithcalledWith使用深度相等deepEqual比对而calledWithMatch才会对参数逐个应用匹配器。要发挥sinon.match.func的作用必须走calledWithMatch/alwaysCalledWithMatch或对应的sinon.assert.*系列断言。匹配器可嵌套sinon.match.func也可以嵌套在其他匹配器中例如sinon.match({ handler: sinon.match.func })用于校验对象中某个属性的类型。八、小结sinon.match.func虽小却是 Sinon 测试体系中函数类型参数断言的标准答案判定规则要求被校验的值是函数typeof value function语义下的可调用实体行为证据仓库配套测试 func.test.js 明确验证了普通函数与箭头函数通过、对象与字符串被拒绝实现原理经由 create-sinon-api.js 委托给sinonjs/samsam的createMatcher并通过 assert.js 与 proxy-call.js 中的test()调用完成比对使用姿势与calledWithMatch、alwaysCalledWithMatch、withArgs、mock expectation 组合即可在回调类、事件处理类、依赖注入类场景中精确断言这里传进来的是一个函数。在编写涉及回调、监听器、middleware、策略函数等大量函数型参数的测试时sinon.match.func能让断言意图一目了然是值得纳入日常测试工具箱的轻量利器。【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址: https://gitcode.com/gh_mirrors/si/sinon创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表