You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest中是否存在类似objectContaining的方法,使用toBe而非toEqual校验属性?

解决方案:严格检查对象属性的引用相等

你遇到的问题核心在于 expect.objectContaining 默认使用 值相等(toEqual) 来匹配属性,而 DOM 元素这类对象,即使是两个独立创建的空按钮,toEqual 会递归比较它们的结构和属性,认为二者相等。但你需要的是 引用相等(toBe) 检查——也就是确保传入的 button 属性是同一个对象引用。

这里有两种简单直接的方法实现你的需求:


方法1:直接获取调用参数并断言引用相等

最直观的方式是从 Jest mock 的调用记录中取出传入的参数,然后单独对 button 属性使用 toBe 断言:

test('foo', () => {
  const button1 = document.createElement('button');
  const button2 = document.createElement('button');
  const foo = jest.fn();

  foo({button: button1});

  // 获取 foo 第一次调用时传入的第一个参数
  const [receivedObj] = foo.mock.calls[0];
  // 严格断言 button 属性是 button1 的引用
  expect(receivedObj.button).toBe(button1);
});

这样修改后,如果传入的是 button2,测试会立即失败——因为 toBe 会检查两个对象是否是同一个内存引用,完全符合你的预期。


方法2:结合 objectContaining 和自定义匹配器

如果你想保留 toBeCalledWith 的写法,可以通过 Jest 的自定义匹配器来实现严格属性检查:

首先扩展 Jest 的匹配器:

expect.extend({
  toBeStrictly(received, expected) {
    const pass = received === expected;
    return {
      pass,
      message: () => pass
        ? `expected ${received} not to be strictly equal to ${expected}`
        : `expected ${received} to be strictly equal to ${expected}`
    };
  }
});

然后在测试中使用:

test('foo', () => {
  const button1 = document.createElement('button');
  const button2 = document.createElement('button');
  const foo = jest.fn();

  foo({button: button1});

  expect(foo).toBeCalledWith(expect.objectContaining({
    button: expect.toBeStrictly(button1)
  }));
});

这个自定义的 toBeStrictly 匹配器会使用严格相等(===)来检查属性值,替代 objectContaining 默认的 toEqual 逻辑。


为什么原始测试会通过?

补充说明一下:你的原始测试中,expect.objectContaining({button: button2}) 能匹配到传入的 {button: button1},是因为 Jest 对 DOM 元素的 toEqual 比较会忽略对象引用,只递归检查元素的标签名、属性、子节点等结构信息。两个新创建的空按钮结构完全一致,所以被判定为“值相等”,但它们本质上是两个独立的对象引用。

内容的提问来源于stack exchange,提问作者Andy Shea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:14:37