如何在Jasmine中使用toEqual断言时忽略实际对象的额外属性?
解决Jasmine中只断言对象特定属性的问题
哦,这个场景我太熟了!手动map确实麻烦,遇到嵌套对象或者复杂结构就完全hold不住。其实Jasmine本身就提供了完美的解决方案,不用自己造轮子~
最常用的方案:jasmine.objectContaining()
这个匹配器的核心就是只检查你指定的属性,忽略对象中其他未声明的属性,完全贴合你的需求。针对你的例子,只需要把断言改成这样:
const actual = [ { a: 1, additionalProp: 'not interesting' }, { a: 2, additionalProp: 'not interesting' } ]; expect(actual).toEqual([ jasmine.objectContaining({ a: 1 }), jasmine.objectContaining({ a: 2 }) ]);
这样断言就会通过,因为它只会验证每个对象里的a属性是否符合预期,完全不在乎additionalProp的存在。
应对复杂嵌套对象
如果你的对象有多层嵌套,这个方法同样适用,只需要嵌套使用jasmine.objectContaining()就行:
const actual = [ { a: 1, extra: 'ignore me', nested: { b: 3, useless: 'foo' } } ]; expect(actual).toEqual([ jasmine.objectContaining({ a: 1, nested: jasmine.objectContaining({ b: 3 }) }) ]);
进阶:处理数组元素结构一致的场景
如果你的数组里所有元素都要符合同一个部分属性结构,还可以结合expect.each()来简化写法:
// 比如断言数组里每个元素的a属性都是数字(或其他统一规则) expect(actual).each((item) => { expect(item).toEqual(jasmine.objectContaining({ a: jasmine.any(Number) })); });
如果不关心数组元素的顺序,还可以用expect.arrayContaining()配合jasmine.objectContaining():
// 只要数组里包含符合条件的元素,不管顺序 expect(actual).toEqual(expect.arrayContaining([ jasmine.objectContaining({ a: 1 }), jasmine.objectContaining({ a: 2 }) ]));
自定义匹配器(适合频繁使用的场景)
如果你的项目里经常需要这种“部分属性断言”,可以自定义一个匹配器来进一步简化代码:
beforeAll(() => { jasmine.addMatchers({ toMatchPartialArray: () => ({ compare(actualArray, expectedPartialArray) { const pass = actualArray.every((actualItem, index) => { const expectedPartial = expectedPartialArray[index]; return jasmine.matchersUtil.equals(actualItem, jasmine.objectContaining(expectedPartial)); }); return { pass, message: pass ? 'Expected array not to match the partial objects' : 'Expected array to match the partial objects, but some items failed the check' }; } }) }); }); // 使用时就像普通断言一样简洁 expect(actual).toMatchPartialArray([{ a: 1 }, { a: 2 }]);
总结
最推荐的还是直接用jasmine.objectContaining(),它是Jasmine原生支持的,不需要额外配置,应付绝大多数场景都足够优雅,比手动map对象要灵活得多。
内容的提问来源于stack exchange,提问作者Liero
相关产品推荐
相关产品推荐

