diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c409ba51bc7..c892678d884a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes - `[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)) ### Chore & Maintenance diff --git a/packages/jest-mock/src/__tests__/index.test.ts b/packages/jest-mock/src/__tests__/index.test.ts index ecceafad3e5f..589b23a568f6 100644 --- a/packages/jest-mock/src/__tests__/index.test.ts +++ b/packages/jest-mock/src/__tests__/index.test.ts @@ -1143,6 +1143,38 @@ describe('moduleMocker', () => { expect.assertions(4); }); + + it('mockImplementationOnce does not bleed into withImplementation', () => { + const mock = jest + .fn(() => 'outside callback') + .mockImplementationOnce(() => 'once'); + + mock.withImplementation( + () => 'inside callback', + () => { + expect(mock()).toBe('inside callback'); + }, + ); + + expect(mock()).toBe('once'); + expect(mock()).toBe('outside callback'); + }); + + it('mockReturnValueOnce does not bleed into withImplementation', () => { + const mock = jest + .fn(() => 'outside callback') + .mockReturnValueOnce('once'); + + mock.withImplementation( + () => 'inside callback', + () => { + expect(mock()).toBe('inside callback'); + }, + ); + + expect(mock()).toBe('once'); + expect(mock()).toBe('outside callback'); + }); }); test('mockReturnValue does not override mockImplementationOnce', () => { diff --git a/packages/jest-mock/src/index.ts b/packages/jest-mock/src/index.ts index 158ad37a51bb..4c4824f478dd 100644 --- a/packages/jest-mock/src/index.ts +++ b/packages/jest-mock/src/index.ts @@ -842,16 +842,20 @@ export class ModuleMocker { // Remember previous mock implementation, then set new one const mockConfig = this._ensureMockConfig(f); const previousImplementation = mockConfig.mockImpl; + const previousSpecificImplementations = mockConfig.specificMockImpls; mockConfig.mockImpl = fn; + mockConfig.specificMockImpls = []; const returnedValue = callback(); if (isPromise(returnedValue)) { return returnedValue.then(() => { mockConfig.mockImpl = previousImplementation; + mockConfig.specificMockImpls = previousSpecificImplementations; }); } else { mockConfig.mockImpl = previousImplementation; + mockConfig.specificMockImpls = previousSpecificImplementations; } }