ARTICLE DETAIL

资讯详情

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

Sinon 自定义匹配器(Custom Matchers)实战指南:用 sinon.match 工厂定制你的参数匹配逻辑

Sinon 自定义匹配器(Custom Matchers)实战指南:用 sinon.match 工厂定制你的参数匹配逻辑 测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载导读当内置匹配器无法精确表达测试预期时sinon.match工厂允许你把任意「值 → 布尔值」的判定函数升级为可复用的匹配器matcher从而在 spy 断言、stub 行为绑定和断言库中实现高度定制的参数匹配。本文将以 Sinon 官方文档 docs/concepts/matchers/custom-matchers.md 为主线结合仓库源码与配套测试讲透自定义匹配器的定义契约、组合方式、错误信息机制与底层调用链读完即可在自己的测试里写出语义清晰、可复用的自定义匹配逻辑。一、核心概念匹配器是什么在进入自定义匹配器之前先明确 Sinon 中「匹配器matcher」的定位。匹配器可以像真实值一样被传给spy.calledWith、spy.calledOn、spy.returned、spy.withArgs以及对应的sinon.assert断言函数。它允许你对预期值进行「更模糊」或「更精确」的描述——例如「任意字符串」「包含某个属性的对象」「匹配某正则的值」。而自定义匹配器就是绕过所有内置规则把判定逻辑完全交给你自己只要提供一个接受值、返回布尔值的函数sinon.match工厂就能把它包装成一个标准匹配器对象。官方文档对自定义匹配器的定义只有两句话却概括了全部契约Custom matchers are created with thesinon.matchfactory. The test function takes a value as the only argument. It must returntrue, when the value matches the expectation andfalseotherwise.即使用sinon.match工厂创建传入的测试函数只接收一个参数待匹配的值该函数必须返回true匹配或false不匹配。二、快速上手最小的自定义匹配器仓库配套测试 docs/tests/docs/matchers/custom-matchers.test.js 给出了一个最小可用示例import t from tap; import sinon from sinon; // 自定义判定函数值在布尔语义上为真即可匹配 function test(value) { return Boolean(value); } // 用 sinon.match 工厂包装成匹配器 const trueIsh sinon.match(test); t.test(custom matcher, (t) { const f sinon.fake(); f(apple pie); // 只要参数是 truthy 值就认为调用匹配 t.ok(f.calledWith(trueIsh)); t.end(); });要点拆解test函数是纯判定逻辑它接收实际调用时传入的参数apple pie返回Boolean(apple pie) true因此f.calledWith(trueIsh)成立匹配器可以像普通值一样参与断言calledWith在比较参数时一旦发现预期值是匹配器对象就不再走深比较deepEqual而是调用匹配器的测试函数工厂函数名字面义明确sinon.match(test)生成的匹配器语义就是「匹配任何 truthy 值」完全由你定义的函数说了算。三、sinon.match 的重载函数参数与内置匹配器sinon.match是 Sinon 匹配体系的总入口它根据参数类型走不同分支。根据官方 API 文档 docs/concepts/matchers/api/match.md函数形式的参数正是自定义匹配器的入口其余重载则是内置匹配器调用形式匹配规则sinon.match(number)要求实际值等于给定数字sinon.match(string)要求实际值是字符串且包含该字符串作为子串sinon.match(regexp)要求实际值是字符串且匹配给定正则sinon.match(object)要求实际值非null/undefined且至少拥有预期对象的所有属性支持嵌套匹配器sinon.match(function)自定义匹配器规则由你提供的判定函数决定即本文主题见 docs/concepts/matchers/custom-matchers.md从源码结构看匹配器工厂并非在 Sinon 仓库内自行实现在 src/create-sinon-api.js 中可以看到match: samsam.createMatcher,即sinon.match直接指向sinonjs/samsam包的createMatcher。这意味着自定义匹配器与deepEqual等深度比较逻辑共享同一套基础库保证匹配器在 spy、assert、mock 各处行为一致。四、底层原理匹配器在断言调用链中如何被使用理解自定义匹配器最好同时看清它在 Sinon 内部的位置。仓库源码中有三处典型消费场景4.1 断言模块sinon.assert.match在 src/sinon/assert.js 中assert.match(actual, expectation)正是用createMatcher把预期值包装后做测试match: function match(actual, expectation) { const matcher createMatcher(expectation); if (matcher.test(actual)) { assert.pass(match); } else { const formatted [ expected value to match, expected ${inspect(expectation)}, actual ${inspect(actual)}, ]; failAssertion(this, join(formatted, \n)); } },这里揭示了一个关键事实无论预期值是数字、字符串、对象还是你自定义的函数Sinon 最终都统一经createMatcher归一化为一个带有.test(value)方法的对象然后调用matcher.test(actual)得到布尔结果。自定义匹配器只是让test方法的实现变成了你的判定函数。4.2 调用记录proxy-call 中的匹配器识别在 src/sinon/proxy-call.js 中createMatcher被用于判断调用参数是否与预期匹配支撑calledWith、withArgs等 API 的底层实现。spy 的withArgs见 src/sinon/spy.js会把匹配参数保存在matchingArguments中后续调用记录比对时一旦发现匹配器就执行其test逻辑而不是做普通相等比较。4.3 错误信息匹配器自带 message自定义匹配器还有一个经常被忽略的能力——为失败断言提供可读的错误信息。在 src/sinon/spy-formatters.js 中function colorSinonMatchText(matcher, calledArg, calledArgMessage) { let calledArgumentMessage calledArgMessage; let matcherMessage matcher.message; if (!matcher.test(calledArg)) { matcherMessage colorizer.red(matcher.message); // ... } return ${calledArgumentMessage} ${matcherMessage}; }格式化器会读取matcher.message并配合matcher.test(calledArg)的结果做颜色标记匹配失败时把匹配器说明标红、实际参数标绿从而在断言失败输出中清晰展示「预期是什么、实际传了什么」。关于message的现状官方文档 docs/concepts/matchers/custom-matchers.md 中以 TODO 注释的形式记录了一个待确认问题——第二参数message目前主要在sinon.assert体系用于生成错误信息仓库维护者尚在评估是否继续保留该参数。从spy-formatters.js的读取逻辑可以推断message字段已经实际参与了失败信息的格式化因此为自定义匹配器设置清晰的描述文本或依赖默认 message有助于提升断言失败时的可读性。五、组合使用and / or / not 让匹配器表达力倍增单个自定义匹配器解决单一判定而 Sinon 为所有匹配器内置了逻辑组合能力。官方文档 docs/concepts/matchers/combining-matchers.md 说明All matchers implementandandor. This allows to logically combine multiple matchers. The result is a new matcher that requires both (and) or one of the matchers (or) to returntrue.配套测试 docs/tests/docs/matchers/combining-matchers.test.js 演示了两种典型组合// 或组合字符串或数字都算匹配 const stringOrNumber sinon.match.string.or(sinon.match.number); const f sinon.fake(); f(apple pie); t.ok(f.calledWith(stringOrNumber)); // 与组合必须是 Book 实例且拥有 pages 属性 const bookWithPages sinon.match .instanceOf(Book) .and(sinon.match.has(pages)); const b new Book(42); const h sinon.fake(); h(b); t.ok(h.calledWith(bookWithPages));把自定义匹配器与内置匹配器组合即可构造「既符合我自定义规则、又属于某类型」「满足自定义规则或落入内置规则」这类复合预期。组合后返回的依然是一个标准匹配器对象因此可以继续参与calledWith、withArgs、assert等所有场景也可以继续链式组合。六、实战模式自定义匹配器的典型使用场景综合文档与源码自定义匹配器最适合以下几类场景语义化断言把复杂的判定条件命名成一个有业务含义的匹配器如上面的trueIsh让测试读起来像自然语言跨用例复用把判定函数抽到公共模块在多个测试文件间共享同一份匹配逻辑避免断言条件散落重复与withArgs配合绑定 stub 行为withArgs接受匹配器因此可以用自定义匹配器精确圈定「哪些参数组合」时 stub 该返回什么见 spy.withArgs 与 stub.withArgs与assert.match配合做对象结构校验自定义匹配器可以作为assert.match(actual, expectation)的 expectation实现深度结构之外的业务规则校验。七、注意事项与边界返回值必须是严格布尔判定函数必须返回true或false。若返回其他 truthy 值虽然测试可能「碰巧」通过但会破坏匹配器契约应使用Boolean()显式转换如官方测试所示只接收一个参数判定函数签名是(value)其余参数会被忽略不要把期望值也塞进函数参数里——它应当是闭包捕获或写死在函数体内的失败信息依赖 message想让失败输出更友好请关注匹配器对象上 message 字段的生成逻辑见上文 4.3 节确保断言失败时能看出匹配器在描述什么组合结果仍是匹配器and/or返回新匹配器可用于继续链式组合但注意逻辑要自洽避免构造出永假的匹配器。八、小结自定义匹配器是 Sinon 匹配体系中最灵活的一块拼图sinon.match(fn)一行代码即可把你的判定函数接入 spy、assert、stub 的整个参数匹配链路。它由sinonjs/samsam的createMatcher归一化处理见 src/create-sinon-api.js经matcher.test(value)驱动判定通过matcher.message参与失败信息格式化见 src/sinon/spy-formatters.js并能与内置匹配器自由组合。官方配套测试 docs/tests/docs/matchers/custom-matchers.test.js 和 docs/tests/docs/matchers/combining-matchers.test.js 是理解全部契约的最佳起点内置匹配器清单可进一步查阅 docs/concepts/matchers/api/index.md。赞分享测试开发工具【免费下载链接】sinonTest spies, stubs and mocks for JavaScript.项目地址https://gitcode.com/gh_mirrors/si/sinon点击查看免费下载相关推荐Sinon Matchers API 完全指南用 sinon.match 实现灵活精确的参数匹配与断言Sinon Matchers API 完全指南用 sinon.match 实现灵活精确的参数匹配与断言 导读 Sinon 的 Matchers匹配器是测试测试开发工具Sinon 匹配器实战用 sinon.match.defined 断言值已定义Sinon 匹配器实战用 sinon.match.defined 断言值已定义 sinon.match.defined 是 Sinon 内置匹配器家族中最测试开发工具Sinon 匹配器指南sinon.match.symbol 精确匹配 Symbol 类型参数Sinon 匹配器指南sinon.match.symbol 精确匹配 Symbol 类型参数 导读 sinon.match.symbol 是 Sinon 匹配测试开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表