[Bug]: `spy.mockReset()` breaks following mock usage
Version
29.7.0
Steps to reproduce
- You write test for function A that calls function B.
- You want to mock function B for all but one test case
- You use
jest.spy(bModule, 'B').mockImplementation(...)by default - In that one specific test case you use
spy.mockRestore()to get real implementation - Boom! All subsequent test cases fail to use mocked implementation or re-mock it.
mockRestore()restored it real hard.
Reproducible case: https://codesandbox.io/p/sandbox/jest-mock-reset-breaks-future-kk4kjr
- Open link
- Run tests
Expected behavior
Able to turn spy to mock implementation in subsequent test cases after test case with mockRestore()
Actual behavior
Unable to get re-mock spy
Additional context
No response
Ok, I found out that re-creating spy itself after calling .mockRestore() helps. e.g.
test("calls real sum", () => {
sumSpy.mockRestore();
expect(callSum(1, 2)).toBe(3);
sumSpy = jest.spyOn(sumModule, "sum").mockImplementation(() => 5);
});
I wonder if this is an expected behaviour or is there a way to keep the spy reference "alive" so that it could be re-mocked without being re-created?
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.
up ^
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.
up (?)
Up :(
@alexey-kozlenkov I suppose it's expected behavior because after you call mockRestore the "spy" itself is removed from original implementation. You can check it by doing something like this:
import { callSum } from './sum-consumer';
import * as sumModule from './sum';
describe('sum consumer', () => {
it('test', () => {
console.log('original impl', sumModule.sum);
let spyOnSum = jest.spyOn(sumModule, 'sum');
spyOnSum.mockImplementation(() => 5);
console.log('spied impl', sumModule.sum);
expect(callSum(1, 1)).toBe(5);
spyOnSum.mockRestore();
/**
* After restoring there is no more "spy wrapper"
* on original function, so any time you do
* spyOnSum.anyMethod() - it acts on "jest.fn"
* that is not connected to original implementation
*/
console.log('impl after restore', sumModule.sum);
expect(callSum(1, 1)).toBe(2);
spyOnSum = jest.spyOn(sumModule, 'sum');
console.log('brand new spied impl', sumModule.sum);
spyOnSum.mockImplementation(() => 3);
expect(callSum(1, 1)).toBe(3);
});
});
So I believe it's expected behavior and you have to re-create a spy after restore.
@dnechay fancy meeting you here Dima! 🥹
Right, that isn't something mentioned in docs, so I found the absence of a mock wrapper around target function after mockReset surprising, thus the bug. But I guess it is what it is.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.
This issue was closed because it has been stalled for 30 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.
This issue was closed because it has been stalled for 30 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.