Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(jest-mock): do not restore mocks when jest.resetAllMocks() is called #13866

Merged
merged 16 commits into from
Feb 15, 2023
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

- `[jest-mock]` Clear mock state when `jest.restoreAllMocks()` is called ([#13867](https://github.com/facebook/jest/pull/13867))
- `[jest-mock]` Prevent `mockImplementationOnce` and `mockReturnValueOnce` bleeding into `withImplementation` ([#13888](https://github.com/facebook/jest/pull/13888))
- `[jest-mock]` Do not restore mocks when `jest.resetAllMocks()` is called ([#13866](https://github.com/facebook/jest/pull/13866))

### Chore & Maintenance

Expand Down
260 changes: 236 additions & 24 deletions packages/jest-mock/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1247,30 +1247,6 @@ describe('moduleMocker', () => {
expect(fn.getMockName()).toBe('jest.fn()');
});

test('after mock reset, the object should return to its original value', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both tests are moved below and extended

const myObject = {bar: () => 'bar'};

const barStub = moduleMocker.spyOn(myObject, 'bar');

barStub.mockReturnValue('POTATO!');
expect(myObject.bar()).toBe('POTATO!');
barStub.mockReset();

expect(myObject.bar()).toBe('bar');
});

test('after resetAllMocks, the object should return to its original value', () => {
const myObject = {bar: () => 'bar'};

const barStub = moduleMocker.spyOn(myObject, 'bar');

barStub.mockReturnValue('POTATO!');
expect(myObject.bar()).toBe('POTATO!');
moduleMocker.resetAllMocks();

expect(myObject.bar()).toBe('bar');
});

test('mockName gets reset by mockRestore', () => {
const fn = jest.fn();
expect(fn.getMockName()).toBe('jest.fn()');
Expand Down Expand Up @@ -1344,6 +1320,134 @@ describe('moduleMocker', () => {
);
});

it('supports clearing a spy', () => {
let methodOneCalls = 0;
const obj = {
methodOne() {
methodOneCalls++;
},
};

const spy1 = moduleMocker.spyOn(obj, 'methodOne');

obj.methodOne();

// The spy and the original function are called.
expect(methodOneCalls).toBe(1);
expect(spy1.mock.calls).toHaveLength(1);

expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);

spy1.mockClear();

// After clearing the spy, the method is still mock function.
expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);

// After clearing the spy, call count is reset.
expect(spy1.mock.calls).toHaveLength(0);
});

it('supports clearing all spies', () => {
let methodOneCalls = 0;
let methodTwoCalls = 0;
const obj = {
methodOne() {
methodOneCalls++;
},
methodTwo() {
methodTwoCalls++;
},
};

const spy1 = moduleMocker.spyOn(obj, 'methodOne');
const spy2 = moduleMocker.spyOn(obj, 'methodTwo');

obj.methodOne();
obj.methodTwo();

// Both spies and both original functions are called.
expect(methodOneCalls).toBe(1);
expect(methodTwoCalls).toBe(1);
expect(spy1.mock.calls).toHaveLength(1);
expect(spy2.mock.calls).toHaveLength(1);

expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);
expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(true);

moduleMocker.clearAllMocks();

// After clearing all mocks, the methods are still mock functions.
expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);
expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(true);

// After clearing all mocks, call counts are reset.
expect(spy1.mock.calls).toHaveLength(0);
expect(spy2.mock.calls).toHaveLength(0);
});

it('supports resetting a spy', () => {
const methodOneReturn = 0;
const obj = {
methodOne() {
return methodOneReturn;
},
};

const spy1 = moduleMocker.spyOn(obj, 'methodOne').mockReturnValue(10);

// Return value is mocked.
expect(methodOneReturn).toBe(0);
expect(obj.methodOne()).toBe(10);

expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);

spy1.mockReset();

// After resetting the spy, the method is still mock functions.
expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);

// After resetting the spy, the method returns the original return value.
expect(methodOneReturn).toBe(0);
expect(obj.methodOne()).toBe(0);
});

it('supports resetting all spies', () => {
const methodOneReturn = 10;
const methodTwoReturn = 20;
const obj = {
methodOne() {
return methodOneReturn;
},
methodTwo() {
return methodTwoReturn;
},
};

moduleMocker.spyOn(obj, 'methodOne').mockReturnValue(100);
moduleMocker.spyOn(obj, 'methodTwo').mockReturnValue(200);

// Return values are mocked.
expect(methodOneReturn).toBe(10);
expect(methodTwoReturn).toBe(20);
expect(obj.methodOne()).toBe(100);
expect(obj.methodTwo()).toBe(200);

expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);
expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(true);

moduleMocker.resetAllMocks();

// After resetting all mocks, the methods are still mock functions.
expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true);
expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(true);

// After resetting all mocks, the methods return the original return value.
expect(methodOneReturn).toBe(10);
expect(methodTwoReturn).toBe(20);
expect(obj.methodOne()).toBe(10);
expect(obj.methodTwo()).toBe(20);
});

it('supports restoring a spy', () => {
let methodOneCalls = 0;
const obj = {
Expand Down Expand Up @@ -1551,6 +1655,59 @@ describe('moduleMocker', () => {
);
});

it('supports resetting a spy', () => {
const methodOneReturn = 0;
const obj = {
get methodOne() {
return methodOneReturn;
},
};

const spy1 = moduleMocker
.spyOn(obj, 'methodOne', 'get')
.mockReturnValue(10);

// Return value is mocked.
expect(methodOneReturn).toBe(0);
expect(obj.methodOne).toBe(10);

spy1.mockReset();

// After resetting the spy, the method returns the original return value.
expect(methodOneReturn).toBe(0);
expect(obj.methodOne).toBe(0);
});

it('supports resetting all spies', () => {
const methodOneReturn = 10;
const methodTwoReturn = 20;
const obj = {
get methodOne() {
return methodOneReturn;
},
get methodTwo() {
return methodTwoReturn;
},
};

moduleMocker.spyOn(obj, 'methodOne', 'get').mockReturnValue(100);
moduleMocker.spyOn(obj, 'methodTwo', 'get').mockReturnValue(200);

// Return values are mocked.
expect(methodOneReturn).toBe(10);
expect(methodTwoReturn).toBe(20);
expect(obj.methodOne).toBe(100);
expect(obj.methodTwo).toBe(200);

moduleMocker.resetAllMocks();

// After resetting all mocks, the methods return the original return value.
expect(methodOneReturn).toBe(10);
expect(methodTwoReturn).toBe(20);
expect(obj.methodOne).toBe(10);
expect(obj.methodTwo).toBe(20);
});

it('supports restoring a spy', () => {
let methodOneCalls = 0;
const obj = {
Expand Down Expand Up @@ -1683,6 +1840,61 @@ describe('moduleMocker', () => {
expect(obj.property).toBe(true);
});

it('supports resetting a spy on the prototype chain', () => {
const methodOneReturn = 0;
const prototype = {
get methodOne() {
return methodOneReturn;
},
};
const obj = Object.create(prototype, {});

const spy1 = moduleMocker
.spyOn(obj, 'methodOne', 'get')
.mockReturnValue(10);

// Return value is mocked.
expect(methodOneReturn).toBe(0);
expect(obj.methodOne).toBe(10);

spy1.mockReset();

// After resetting the spy, the method returns the original return value.
expect(methodOneReturn).toBe(0);
expect(obj.methodOne).toBe(0);
});

it('supports resetting all spies on the prototype chain', () => {
const methodOneReturn = 10;
const methodTwoReturn = 20;
const prototype = {
get methodOne() {
return methodOneReturn;
},
get methodTwo() {
return methodTwoReturn;
},
};
const obj = Object.create(prototype, {});

moduleMocker.spyOn(obj, 'methodOne', 'get').mockReturnValue(100);
moduleMocker.spyOn(obj, 'methodTwo', 'get').mockReturnValue(200);

// Return values are mocked.
expect(methodOneReturn).toBe(10);
expect(methodTwoReturn).toBe(20);
expect(obj.methodOne).toBe(100);
expect(obj.methodTwo).toBe(200);

moduleMocker.resetAllMocks();

// After resetting all mocks, the methods return the original return value.
expect(methodOneReturn).toBe(10);
expect(methodTwoReturn).toBe(20);
expect(obj.methodOne).toBe(10);
expect(obj.methodTwo).toBe(20);
});

it('supports restoring a spy on the prototype chain', () => {
let methodOneCalls = 0;
const prototype = {
Expand Down
Loading