I’m aware of toHaveBeenCalledWith
and toHaveBeenNthCalledWith
, but I want a call with certain parameter exactly once (or, more generally, N times). How do I check that? In other words, I care about number of calls and about arguments passed, but not about order of calls.
If I’d try to name a function to do such check, it would be e.g. toHaveBeenCalledTimesWith
.
4
You can use expect.extend
to add the toHaveBeenCalledTimesWith
matcher to Jest.
e.g.
index.test.js
:
export function toHaveBeenCalledTimesWith(received, times, ...args) {
const { printReceived, printExpected, matcherHint } = this.utils;
const actual = received.mock.calls[0];
const invokedTimes = received.mock.calls.length === times;
const pass = invokedTimes && this.equals(args, actual);
return {
pass,
message: () => {
return pass
? matcherHint('.not.toHaveBeenCalledTimesWith', 'received', '') +
'nn' +
`Expected mock to be invoked ${times} times other than ${received.mock.calls.length} times or ${received.mock.calls.length} times with ` +
`arguments other than ${printExpected(args)}, but was invoked ` +
`${printReceived(received.mock.calls.length)} times with ${printReceived(...actual)}`
: matcherHint('.toHaveBeenCalledTimesWith') +
'nn' +
(invokedTimes
? `Expected mock function to have been called ${times} times with ` +
`${printExpected(args)}, but it was called with ${printReceived(...actual)}`
: `Expected mock function to have been called ${times} times, but it was called ` +
`${printReceived(received.mock.calls.length)} times`);
},
actual: received,
};
}
expect.extend({ toHaveBeenCalledTimesWith });
describe('first', () => {
test('should pass 1', () => {
const fn = jest.fn();
fn('a');
fn('a');
fn('a');
expect(fn).toHaveBeenCalledTimesWith(3, 'a');
});
test('should pass 2', () => {
const fn = jest.fn();
fn('a');
fn('a');
fn('a');
expect(fn).toHaveBeenCalledTimesWith(2, 'a');
});
});
Test result:
FAIL stackoverflow/78977962/index.test.js
first
√ should pass 1 (2 ms)
× should pass 2 (1 ms)
● first › should pass 2
expect(received).toHaveBeenCalledTimesWith(expected)
Expected mock function to have been called 2 times, but it was called 3 times
42 | fn('a');
43 | fn('a');
> 44 | expect(fn).toHaveBeenCalledTimesWith(2, 'a');
| ^
45 | });
46 | });
47 |
at Object.toHaveBeenCalledTimesWith (stackoverflow/78977962/index.test.js:44:16)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 0.836 s, estimated 1 s
Ran all test suites related to changed files.