Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest: Better way to disable console inside unit tests

People also ask

How do I avoid console error in Jest?

Here is my current approach: describe("Some description", () => { let consoleSpy; beforeEach(() => { if (typeof consoleSpy === "function") { consoleSpy. mockRestore(); } }); test("Some test that should not output errors to jest console", () => { expect. assertions(2); consoleSpy = jest.

How do I cover console log in Jest?

If using Jest test framework, you can turn off all console messages by one command: jest --silent .


For particular spec file, Andreas's is good enough. Below setup will suppress console.log statements for all test suites,

jest --silent

(or)

To customize warn, info and debug you can use below setup

__tests__/setup.js or jest-preload.js configured in setupFilesAfterEnv

global.console = {
  log: jest.fn(), // console.log are ignored in tests

  // Keep native behaviour for other methods, use those to print out things in your own tests, not `console.log`
  error: console.error,
  warn: console.warn,
  info: console.info,
  debug: console.debug,
};

jest.config.js

module.exports = {
    verbose: true,
    setupTestFrameworkScriptFile: "<rootDir>/__tests__/setup.js",
};

Jest v24.x Note: setupTestFrameworkScriptFile is deprecated in favor of setupFilesAfterEnv.

module.exports = {
    verbose: true,
    setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
};

If you wanna do it just for a specific test:

beforeEach(() => {
  jest.spyOn(console, 'warn').mockImplementation(() => {});
});

As every test file runs in its own thread there is no need to restore it if you want to disable it for all test in one file. For the same reason you can also just write

console.log = jest.fn()
expect(console.log).toHaveBeenCalled();

I found that the answer above re: suppressing console.log across all test suites threw errors when any other console methods (e.g. warn, error) were called since it was replacing the entire global console object.

This somewhat similar approach worked for me with Jest 22+:

package.json

"jest": {
  "setupFiles": [...],
  "setupTestFrameworkScriptFile": "<rootDir>/jest/setup.js",
  ...
}

jest/setup.js

jest.spyOn(global.console, 'log').mockImplementation(() => jest.fn());

Using this method, only console.log is mocked and other console methods are unaffected.


To me a more clear/clean way (reader needs little knowledge of the jest API to understand what is happening), is to just manually do what mockRestore does:

// at start of test you want to suppress
const consoleLog = console.log;
console.log = jest.fn();

// at end of test
console.log = consoleLog;

beforeAll(() => {
    jest.spyOn(console, 'log').mockImplementation(() => {});
    jest.spyOn(console, 'error').mockImplementation(() => {});
    jest.spyOn(console, 'warn').mockImplementation(() => {});
    jest.spyOn(console, 'info').mockImplementation(() => {});
    jest.spyOn(console, 'debug').mockImplementation(() => {});
});

Weirdly the answers above (except Raja's great answer but I wanted to share the weird way the others fail and how to clear the mock so no one else wastes the time I did) seem to successfully create the mock but don't suppress the logging to the console.

Both

const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});

and

global console = {
   warn: jest.fn().mockImplementation(() => {});
}

successfully install the mock (I can use expect(console.warn).toBeCalledTimes(1) and it passes) but it still outputs the warning even though the mock implementation seemingly should be replacing the default (this is in a jsdom environment).

Eventually I found a hack to fix the problem and put the following in the file loaded with SetupFiles in your config (note that I found sometimes global.$ didn't work for me when putting jquery into global context so I just set all my globals this way in my setup).

const consoleWarn = jest.spyOn(console, 'warn').mockImplementation(() => {});
const consoleLog = jest.spyOn(console, 'log').mockImplementation(() => {});
const consoleDebug = jest.spyOn(console, 'debug').mockImplementation(() => {});
const consoleError = jest.spyOn(console, 'error').mockImplementation(() => {});


Object.defineProperty(global, 'console', {value: {
                                            warn: consoleWarn,
                                            log: consoleLog,
                                            debug: consoleDebug,
                                            error: consoleError}});

It feels ugly and I then have to put code like the following in each test file since beforeEach isn't defined in the files referenced by SetupFiles (maybe you could put both in SetupFilesAfterEnv but I haven't tried).

beforeEach(() => {
  console.warn.mockClear();
});