Jest: лучший способ отключить консоль внутри модульных тестов

Интересно, есть ли лучший способ отключить консольные ошибки внутри конкретного теста Jest (т.е. восстановить исходную консоль до/после каждого теста).

Вот мой текущий подход:

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.spyOn(console, "error").mockImplementation();

    // some function that uses console error
    expect(someFunction).toBe("X");
    expect(consoleSpy).toHaveBeenCalled();
  });

  test("Test that has console available", () => {
    // shows up during jest watch test, just as intended
    console.error("test");
  });
});

Есть ли более чистый способ сделать то же самое? Я бы хотел избежать spyOn, но mockRestore работает только с ним.

Спасибо!

Ответ 1

Поскольку каждый тестовый файл работает в своем потоке, нет необходимости его восстанавливать, если вы хотите отключить его для всех тестов в одном файле. По той же причине вы также можете просто написать

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

Ответ 2

Для конкретного спецификационного файла Андреас достаточно хорош. Ниже настройка console.log операторы console.log для всех наборов тестов,

jest --silent

(или же)

Чтобы настроить warn, info and debug вы можете использовать ниже настройки

__tests __/setup.js

global.console = {
    log: jest.fn()
}

jest.config.js

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

Jest v24.x Примечание: setupTestFrameworkScriptFile не рекомендуется в пользу setupFilesAfterEnv.

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

Ответ 3

Я обнаружил, что ответ выше: подавление console.log во всех тестовых наборах приводило к ошибкам при вызове любых других console методов (например, warn, error), поскольку он заменял весь глобальный объект console.

Этот несколько похожий подход работал для меня с Джестом 22+:

package.json

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

JEST/setup.js

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

При использовании этого метода console.log только console.log а другие методы console не затрагиваются.

Ответ 4

Для меня более понятный/понятный способ (читателю не нужно много знаний о jest API, чтобы понять, что происходит), это просто вручную делать то, что делает mockRestore:

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

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

Ответ 5

Другой подход заключается в использовании process.env.NODE_ENV. Таким образом, можно выборочно выбирать, что показывать (или нет) во время выполнения тестов:

if (process.env.NODE_ENV === 'development') {
  console.log('Show output only while in "development" mode');
} else if (process.env.NODE_ENV === 'test') {
  console.log('Show output only while in "test" mode');
}

или же

const logDev = msg => {
  if (process.env.NODE_ENV === 'development') {
    console.log(msg);
  }
}
logDev('Show output only while in "development" mode');

Это потребует размещения этой конфигурации в package.json:

"jest": {
  "globals": {
    "NODE_ENV": "test"
  }
}

Обратите внимание, что этот подход не является прямым решением исходного вопроса, но дает ожидаемый результат, если у вас есть возможность обернуть console.log указанным условием.