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?
There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.
mock replaces one module with either just jest. fn , when you call it with only the path parameter, or with the returning value of the function you can give it as the second parameter.
mockFn.mockClear() Often this is useful when you want to clean up a mocks usage data between two assertions.
In order to run a piece of code before every test, Jest has a beforeEach hook, which we can use as follows. Clears the mock. calls and mock. instances properties of all mocks.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With