diff --git a/docs/en/JestObjectAPI.md b/docs/en/JestObjectAPI.md index f73bb6b1c1f0..22018e4dac39 100644 --- a/docs/en/JestObjectAPI.md +++ b/docs/en/JestObjectAPI.md @@ -24,6 +24,7 @@ The `jest` object is automatically in scope within every test file. The methods - [`jest.dontMock(moduleName)`](#jestdontmockmodulename) - [`jest.clearAllMocks()`](#jestclearallmocks) - [`jest.resetAllMocks()`](#jestresetallmocks) + - [`jest.restoreAllMocks()`](#jestrestoreallmocks) - [`jest.resetModules()`](#jestresetmodules) - [`jest.runAllTicks()`](#jestrunallticks) - [`jest.runAllTimers()`](#jestrunalltimers) @@ -179,8 +180,11 @@ Resets the state of all mocks. Equivalent to calling `.mockReset()` on every moc Returns the `jest` object for chaining. -### `jest.resetModules()` +### `jest.restoreAllMocks()` +##### available in Jest **20.1.0+** +Restores all mocks back to their original value. Equivalent to calling `.mockRestore` on every mocked function. Beware that `jest.restoreAllMocks()` only works when mock was created with `jest.spyOn`; other mocks will require you to manually restore them. +### `jest.resetModules()` Resets the module registry - the cache of all required modules. This is useful to isolate modules where local state might conflict between tests. Example: diff --git a/packages/jest-mock/src/__tests__/jest_mock.test.js b/packages/jest-mock/src/__tests__/jest_mock.test.js index 4aa0645df5cd..5553a0d2eae6 100644 --- a/packages/jest-mock/src/__tests__/jest_mock.test.js +++ b/packages/jest-mock/src/__tests__/jest_mock.test.js @@ -488,5 +488,41 @@ describe('moduleMocker', () => { moduleMocker.spyOn({method: 10}, 'method'); }).toThrow(); }); + + it('supports restoring 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'); + + // First, we call with the spies: both spies and both original functions + // should be called. + obj.methodOne(); + obj.methodTwo(); + expect(methodOneCalls).toBe(1); + expect(methodTwoCalls).toBe(1); + expect(spy1.mock.calls.length).toBe(1); + expect(spy2.mock.calls.length).toBe(1); + + moduleMocker.restoreAllMocks(); + + // Then, after resetting all mocks, we call methods again. Only the real + // methods should bump their count, not the spies. + obj.methodOne(); + obj.methodTwo(); + expect(methodOneCalls).toBe(2); + expect(methodTwoCalls).toBe(2); + expect(spy1.mock.calls.length).toBe(1); + expect(spy2.mock.calls.length).toBe(1); + }); }); }); diff --git a/packages/jest-mock/src/index.js b/packages/jest-mock/src/index.js index 204239a81547..bdfbbf26b2c0 100644 --- a/packages/jest-mock/src/index.js +++ b/packages/jest-mock/src/index.js @@ -165,6 +165,7 @@ class ModuleMockerClass { _environmentGlobal: Global; _mockState: WeakMap; _mockConfigRegistry: WeakMap; + _spyState: Set<() => void>; ModuleMocker: Class; /** @@ -176,6 +177,7 @@ class ModuleMockerClass { this._environmentGlobal = global; this._mockState = new WeakMap(); this._mockConfigRegistry = new WeakMap(); + this._spyState = new Set(); this.ModuleMocker = ModuleMockerClass; } @@ -302,6 +304,10 @@ class ModuleMockerClass { f._isMockFunction = true; f.getMockImplementation = () => this._ensureMockConfig(f).mockImpl; + if (typeof restore === 'function') { + this._spyState.add(restore); + } + this._mockState.set(f, this._defaultMockState()); this._mockConfigRegistry.set(f, this._defaultMockConfig()); @@ -579,6 +585,7 @@ class ModuleMockerClass { object[methodName] = this._makeComponent({type: 'function'}, () => { object[methodName] = original; }); + object[methodName].mockImplementation(function() { return original.apply(this, arguments); }); @@ -595,6 +602,11 @@ class ModuleMockerClass { this._mockConfigRegistry = new WeakMap(); this._mockState = new WeakMap(); } + + restoreAllMocks() { + this._spyState.forEach(restore => restore()); + this._spyState = new Set(); + } } export type ModuleMocker = ModuleMockerClass; diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index 517589819518..09225d4dabc8 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -462,6 +462,10 @@ class Runtime { this._mockFactories[moduleID] = mockFactory; } + restoreAllMocks() { + this._moduleMocker.restoreAllMocks(); + } + resetAllMocks() { this._moduleMocker.resetAllMocks(); }