“ .toMatchObject”和“ objectContaining”之间有什么区别


69

我已经编写了以下测试:

it('Can decrement the current step', function () {
    expect(reducer(TestState, { type: 'GOTO_PREVIOUS_STEP' })).toMatchObject({ currentStep: 4 });
});

it('Can decrement the current step v2', function () {
    expect(reducer(TestState, { type: 'GOTO_PREVIOUS_STEP' })).toEqual(expect.objectContaining({ currentStep: 4 }));
});

他们两个似乎都通过了测试,两者之间有什么区别吗?它们之间对性能有影响吗?

Answers:


105

通过查看文档以及我自己的实验来确认它,不同之处在于对嵌套在作为期望传递的道具中的对象的处理。

如果期望对象具有一个包含对象的属性,该属性包含实际对象的等效属性中的一些但不是全部属性,则:

  • 如docs所示, toMatchObject仍将通过。

  • Expect.objectContaining将失败(除非您使用Expect.objectContaining()在期望对象本身中声明该属性)

示例(在Jest中测试):

  // objectContaining, with nested object, containing full props/values
  // PASSES
  expect({ position: { x: 0, y: 0 } }).toEqual(expect.objectContaining({
    position: {
      x: expect.any(Number),
      y: expect.any(Number)
    }
  }));

  // objectContaining, with nested object, containing partial props/values
  // FAILS
  expect({ position: { x: 0, y: 0 } }).toEqual(expect.objectContaining({
    position: {
      x: expect.any(Number)
    }
  }));

  // objectContaining, with nested object, also declared with objectContaining, containing partial props/values
  // PASSES
  expect({ position: { x: 0, y: 0 } }).toEqual(expect.objectContaining({
    position: expect.objectContaining({
      x: expect.any(Number)
    })
  }));

  // toMatchObject, with nested object, containing full props/values
  // PASSES
  expect({ position: { x: 0, y: 0 } }).toMatchObject({
    position: {
      x: expect.any(Number),
      y: expect.any(Number)
    }
  });

  // toMatchObject, with nested object, containing partial props/values
  // PASSES
  expect({ position: { x: 0, y: 0 } }).toMatchObject({
    position: {
      x: expect.any(Number)
    }
  });

5
“计算机科学中只有两件难事:缓存失效和命名事”
Ricky Boyce

4

我的想法是,可以使用expect.objectContaining以及其他类似的匹配器)代替传递给其他匹配器的“对象”中的文字值。

这个例子来自文档:

test('onPress gets called with the right thing', () => {
  const onPress = jest.fn();
  simulatePresses(onPress);
  expect(onPress).toBeCalledWith(expect.objectContaining({
    x: expect.any(Number),
    y: expect.any(Number),
  }));
});

因此,尽管它们在您的示例中似乎做相同的事情,但它们expect.*也可以通过其他方式使用。


3

即使这两种构造之间在功能上没有差异,这还是一个为什么的示例expect.objectContaining-尽管与相比toMatchObject,它既冗长又麻烦,但仍然有用:

describe('list of X', () => {
  it('should contain an element with a specific ID', () => {
    const listOfItems = uut.getItems();
    expect(listOfItems).toContainEqual(expect.objectContaining({id: 'some-id'}));
  });
});

即使listOfItems包含此类项目(即,除了“ id”以外的其他字段),

[
  {id: 'some-id', other: 'fields'},
  {id: 'some-other-id', even: 'more-fields'}
]

仍然expect.objectContaining允许按照您的期望(即严格基于ID)实现比较的简单方法;toMatchObject根本不能在这里使用。因此,虽然toMatchObject简短易读,但两者的较长结构却更为通用,并具有更大的灵活性,因为它可以以无法使用的方式加以利用toMatchObject()

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.