简体   繁体   中英

Jest mock function arguments don't match when using immutable data structures

When trying to test the arguments passed to the function with Jest's .toHaveBeenCalledWith() method, the test fails if I am treating with immutable data structures using ImmutableJS library. The test fails with the message similar to this:

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

The test looks similar to this:

const expectedArgs = Map({
  foo: true,
  bar: 'baz'
});

const foo = jest.fn();
bar();
expect(foo).toHaveBeenCalledWith(expectedArgs);

And the function similar to this:

const bar = () => {
  const baz = Map({});
  const bazModified = baz.set('foo', true).set('bar', 'baz');
  foo(bazModified);
}

I realized that if I pass the arguments in this manner everything works fine:

const bar = () => {
  const baz = Map({
    foo: true,
    bar: 'baz'
  });
  foo(baz);
}

The problem is that this is a big simplification of my function's logic and I have to use .set to construct the object. Does anybody have an idea why the approach with .set is failing to evaluate correctly?

So your test is failing because toHaveBeenCalledWith only passes if the instances of the entities are exactly the same. It is similar to the following, which also fails:

const expectedArgs = Map({
  foo: true,
  bar: 'baz'
});

const input =  Map({
  foo: false,
  bar: 'baz'
});

const result = input.set('foo', true);

expect(result).toBe(expectedArgs);

This, on the other hand, does work:

expect(result).toEqual(expectedArgs);

Because that performs a deep equal.

There is no way you will be able to test equality with toHaveBeenCalledWith , because baz.set('foo', true) will always return a new instance (which is the point of using immutable data).

I don't think there is a way to make toHaveBeenCalledWith behave like toEqual , so I guess the way to go is to manually test the mock call with toEqual :

const expectedArgs = Map({
  foo: true,
  bar: 'baz'
});

const foo = jest.fn();
bar();
// foo.mock.calls[0][0] returns the first argument of the first call to foo
expect(foo.mock.calls[0][0]).toEqual(expectedArgs);

See the documentation on toBe , toEqual , and mock calls

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM