Jest: how to mock console when it is used by a third-party-library? Jest: how to mock console when it is used by a third-party-library? javascript javascript

Jest: how to mock console when it is used by a third-party-library?


You have to use global to access objects in the global context

global.console = {warn: jest.fn()}expect(console.warn).toBeCalled()

or use jest.spyOn added in 19.0.0

jest.spyOn(global.console, 'warn')


Use jest.spyOn() and mockRestore().

const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation();...consoleWarnMock.mockRestore();

The accepted answer does not restore the original console.warn() and will "compromise" the other tests inside the same file (if console.warn() is used inside the other tests or the code being tested).

FYI if you use console.warn = jest.fn() in a test file, it won't affect other test files (e.g console.warn will be back to its original value in the other test files).

Advice: you can call consoleWarnMock.mockRestore() inside afterEach()/afterAll() to be sure that even if a test crashes, it won't compromise the other tests from the same file (e.g ensures the tests inside the same file are fully isolated).

Full example:

const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation();console.warn('message1'); // Won't be displayed (mocked)console.warn('message2'); // Won't be displayed (mocked)expect(console.warn).toHaveBeenCalledTimes(2);expect(consoleWarnMock).toHaveBeenCalledTimes(2); // Another syntaxexpect(console.warn).toHaveBeenLastCalledWith('message2');expect(consoleWarnMock).toHaveBeenLastCalledWith('message2'); // Another syntaxexpect(consoleWarnMock.mock.calls).toEqual([['message1'], ['message2']]);expect(console.warn.mock.calls).toEqual([['message1'], ['message2']]);consoleWarnMock.mockRestore(); // IMPORTANT//console.warn.mockRestore(); // Another syntaxconsole.warn('message3'); // Will be displayed (not mocked anymore)expect(consoleWarnMock).toHaveBeenCalledTimes(0); // Not counting anymoreexpect(consoleWarnMock.mock.calls).toEqual([]);//expect(console.warn.mock.calls).toEqual([]); // Crash

You cannot write

console.warn = jest.fn().mockImplementation();... console.warn.mockRestore();

because it won't restore the original console.warn().

/!\ With mockImplementationOnce() you will still need to call consoleWarnMock.mockRestore():

// /!\const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementationOnce(() => {});console.warn('message1'); // Won't be displayed (mocked)expect(console.warn).toHaveBeenCalledTimes(1);expect(consoleWarnMock).toHaveBeenCalledTimes(1); // Another syntaxexpect(console.warn).toHaveBeenLastCalledWith('message1');expect(consoleWarnMock).toHaveBeenLastCalledWith('message1'); // Another syntaxexpect(consoleWarnMock.mock.calls).toEqual([['message1']]);expect(console.warn.mock.calls).toEqual([['message1']]);console.warn('message2'); // Will be displayed (not mocked anymore)// /!\expect(console.warn).toHaveBeenCalledTimes(2); // BAD => still countingexpect(consoleWarnMock.mock.calls).toEqual([['message1'], ['message2']]);expect(console.warn.mock.calls).toEqual([['message1'], ['message2']]);consoleWarnMock.mockRestore(); // IMPORTANT//console.warn.mockRestore(); // Another syntaxconsole.warn('message3'); // Will be displayed (not mocked anymore)expect(consoleWarnMock).toHaveBeenCalledTimes(0); // Not counting anymoreexpect(consoleWarnMock.mock.calls).toEqual([]);//expect(console.warn.mock.calls).toEqual([]); // Crash

You can also write:

const assert = console.assert;console.assert = jest.fn();...console.assert = assert;