86

I'm using jest to test my react components and I'm using expect(...).toBeCalledWith(...); to test if a function has been called with specific parameters, and it works fine with value types.

The problem is I want to test a function that takes object as a parameter so when you call expect(myFunc).toBeCalledWith(object); the test always fails because of course the two object compared to each other do not have the same reference.

so how can I solve this problem ?

a sample code of what I'm trying to test is

it('the function should be called with the correct object', () => {
    api.submitForm = jest.fn().mockReturnValue(Promise.resolve());
    const wrapper = shallow(<component />);
    const instance = wrapper.instance();
    instance.submitForm();
    const object = {
      foo : 'foo',
      bar: 'bar'
    };
    // this always fails even the function is called with the same object values
    expect(api.submitForm).toBeCalledWith(object);
  });

An error message would be something like this

Expected mock function to have been called with:
      [{"bar": "bar", "foo": "foo"}]
    But it was called with:
      [{"bar": "bar", "foo": "foo"}]

Update

it seems the below code works fine

  expect(api.submitForm).toBeCalledWith(
    expect.objectContaining({
     foo : 'foo',
      bar: 'bar'
    }),
  );

however, if the object contains a property with array value, the above solution doesn't work

const obj = {
  foo : ['foo1', 'foo2'],
  bar: 'bar'
}
5
  • The problem could be something else. I have used the above pattern in my code and it works as expected Commented Dec 23, 2017 at 14:39
  • Mention the jest version please... Commented Dec 23, 2017 at 14:41
  • The jest doc itself at here shows that they are comparing the value, not the reference, facebook.github.io/jest/docs/en/… Commented Dec 23, 2017 at 14:50
  • I'm using jest 20.0.4, and the problem happens if you have an array property in your object Commented Dec 23, 2017 at 15:02
  • the second solution works now I've discovered a typo in my code. Commented Dec 23, 2017 at 15:06

3 Answers 3

104

Looking at the jest doc (https://jestjs.io/docs/expect#expectobjectcontainingobject). It seems you can do something like this:

 expect(api.submitForm).toBeCalledWith(
    expect.objectContaining({
     foo : 'foo',
      bar: 'bar'
    }),
  );
4
  • This would work. But the real intention of expect.objectContaining is slightly different Commented Dec 23, 2017 at 14:43
  • 8
    this works fine actually, but the problem if your object contains an array property Commented Dec 23, 2017 at 15:00
  • Man I love good documentation! Thanks [jest] team!
    – tim.rohrer
    Commented May 2, 2022 at 20:59
  • This doesn't work if being expected object contains a object in itself, and we need to match on this nested object property. What can be done in this case? Ex {headers:{a:10},z:20} need to match on "a" equals 10
    – Nandan Raj
    Commented Mar 9, 2023 at 10:35
9

you can use .mock.calls[callIdx][paramIdx]
description + example: https://stackoverflow.com/a/41939921/2519073

in your case

expect(api.submitForm.mock.calls[0][0]).toMatchObject( // use whatever matcher you want
    {
      foo : ['foo1', 'foo2'],
      bar: 'bar'
    },
  );
3

In case you your function is called with arguments

function update( userId, partialUserObject ){
   // update logic
}

You can use

expect(update).toBeCalledWith('mockUserId',
   expect.objectContaining({
     username:'hello-world',
     displayName: 'Hello World'
   })
);

Not the answer you're looking for? Browse other questions tagged or ask your own question.