Which is the correct Jest Spy On usage

I am able to successfully run my test (mock i18next.t in this case), without specifying the spy wrapper. Why? And what is the difference?

Based on docs and answers here

const spy = jest.spyOn(i18next, 't');

expect(spy).toHaveBeenCalledWith('errorCharacterLength', { min: 5, max: 10 });
expect(result).toEqual(i18next.t('errorCharacterLength', { min: 5, max: 10 }));

What’s the difference with this one when it still works. Tests succeeds.

jest.spyOn(i18next, 't');

expect(i18next.t).toHaveBeenCalledWith('errorCharacterLength', { min: 5, max: 10 });
expect(result).toEqual(i18next.t('errorCharacterLength', { min: 5, max: 10 }));

It’s not clear to me if under the hood, spyOn mocks i18next. And what does it mean for the second expect statement?

  • In neither case is t actually called. And in both cases the second expectation doesn’t make any sense – the result of calling it should be equal to the result of calling it? Only the test double is actually being tested, and all that’s tested is that it does what it’s set up to do.

    – 

The first example should work. That is a correct way to set a variable to a spy. The value of the variable will be a Jest mock function and your syntax looks right. The reason the second one works is that Jest “monkey patches” the spied function so that i18next.t is replaced by a Jest mock function that passes through to the original function as well. Since after calling spyOn the t() method is replaced by a Jest mock function you are able to call expect assertions against i18next.t because it is now a Jest mock.

Leave a Comment