web-dev-qa-db-ja.com

「.toMatchObject」と「objectContaining」の違いは何ですか

次のテストを作成しました。

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 }));
});

どちらもテストに合格したようですが、両者に違いはありますか?それらの間にパフォーマンスの影響はありますか?

51
Julito Sanchis

ドキュメントを見て、それを確認するための私自身の実験から、違いは期待として渡されたプロップ内にネストされたオブジェクトの処理にあります。

期待オブジェクトが、実際のオブジェクトの同等のプロパティにあるプロパティのすべてではなくを含むオブジェクトを含むプロパティを持つ場合、次のようになります。

  • 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)
    }
  });
19
Jonathan

私の考えでは、他のマッチャーに渡す「オブジェクト」内のリテラル値の代わりに、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
David

2つの構造に機能的な違いがない場合でも、_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は短くて読みやすいですが、2つの長い構造はより一般的であり、toMatchObject()ができない方法で使用できるため、柔軟性が高くなります。

0
d4vidi