Jest中如何使用类数组语法递归校验含[Symbol.iterator]的可迭代对象?
Jest 中可迭代对象的类数组断言支持说明
原生断言的实际能力边界
toBe断言完全无法匹配你示例中的写法。它基于Object.is做严格的引用相等校验,只要待校验对象和期望对象不是同一个内存地址的引用,哪怕结构完全一致也会抛出断言失败,根本不会识别对象上的[Symbol.iterator]方法。- 原生
toEqual虽然支持深度结构对比,但不会自动识别自定义类实现的可迭代逻辑:它只会遍历对象的自有可枚举属性做对比,对于你自定义的Matrix、Vector类实例,它会优先对比类上挂载的属性(比如Vector类内部的values私有字段),不会主动触发迭代逻辑去读取yield出来的内容做递归对比。注意:Jest的
toEqual仅对Set、Map这类内置可迭代类型做了特殊适配,自定义实现的可迭代类不在原生适配范围内。
符合递归校验要求的实现方案
要实现你需要的“自动遍历所有层级的可迭代元素、和类数组期望值做递归匹配”的效果,不需要引入第三方依赖,两种常用落地方式都可以快速实现:
- 编写通用递归转换工具函数
核心逻辑是写一个递归方法:碰到实现了[Symbol.iterator]的对象,就遍历取出所有迭代产出的元素,再对每个元素重复执行相同的转换逻辑,最终生成纯数组/原始值的嵌套结构,再交给Jest原生的toEqual做深度对比。示例代码:// 递归将任意深度的可迭代对象转为纯可序列化结构 const iterableToPlain = (target) => { // 不具备迭代能力的值,直接返回 if (typeof target?.[Symbol.iterator] !== 'function') return target; // 遍历迭代值,对每个产出元素递归执行转换 return Array.from(target, child => iterableToPlain(child)); } // 测试用例中使用 test('矩阵值匹配单位矩阵', () => { const matrix = new Matrix(); expect(iterableToPlain(matrix)).toEqual([ [1, 0, 0], [0, 1, 0], [0, 0, 1], ]) })注意:按照你给出的
Vector类的当前实现,迭代器会把内部的values数组作为单独的迭代值产出,生成的结构会比你期望的多嵌套一层数组,需要调整Vector的迭代逻辑(比如改成yield* this.values,直接把内部数组的元素依次yield出来)才能和示例中的期望结构完全匹配。 - 封装自定义Jest匹配器
如果不想在每个测试用例里手动调用转换函数,可以把递归转换+对比的逻辑封装成Jest自定义匹配器,直接实现类似你示例中写的断言写法,例如扩展出toIterateDeepEqual匹配器,底层复用上面的递归转换逻辑做深度对比即可。
内容的提问来源于stack exchange,提问作者hopeless-programmer
相关产品推荐
相关产品推荐

