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

103

Интересно , если есть лучший способ блокирует сообщения об ошибках консоли внутри в конкретном тесте 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только кажется, что с этим можно работать .

Благодаря!

Apidcloud
источник

Ответы:

136

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

jest --silent

(или же)

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

__tests __ / setup.js или jest-preload.js, настроенные в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 Примечание: setupTestFrameworkScriptFile устарел в пользу setupFilesAfterEnv.

module.exports = {
    verbose: true,
    setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
};
Раджа Джаганатан
источник
2
Привет! setupTestFrameworkScriptFileустарел в пользу setupFilesAfterEnv.
elhoucine
1
Mocking global.console- это действительно простой способ, и его можно выполнить с помощью любой конфигурации setupFilesAfterEnv . Остерегайтесь имитировать все собственные методы consoleобъекта, иначе вы можете столкнуться с другими неожиданными ошибками.
Vadorequest
53

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

console.log = jest.fn()
expect(console.log).toHaveBeenCalled();
Андреас Кёберле
источник
1
Спасибо за информацию по этому поводу. В этом есть смысл :) Я искал способ сделать это таким образом только внутри конкретного теста без необходимости его восстанавливать (сначала я думал, что это поведение по умолчанию), но я думаю, что beforeEach справится с задачей.
Apidcloud
51

Если вы хотите сделать это только для определенного теста:

beforeEach(() => {
  jest.spyOn(console, 'warn').mockImplementation(() => {});
});
Константин
источник
1
это гениально!
sheriff_paul
21

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

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

package.json

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

jest / setup.js

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

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

никб
источник
7

Для меня более ясный / чистый способ (читателю нужно немного знать 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;
Майкл Ликури
источник
1
Вам также необходимо охватить console.info, console.error, console.warn и т. Д.
Майкл Орил,
1
@ michael-liquori зачем перезапускать console.log? Думаю, после каждого описания
насмешки
2
@Jhonatan Я не думаю, что это проясняется после каждого описания, хотя я не проверял это недавно, чтобы быть уверенным. Согласно jest docs, есть параметр конфигурации clearMocksи, resetMocksно они оба по умолчанию false, и ни один из них не восстанавливает исходную реализацию, даже если установлено значение true. И, учитывая, что это параметр конфигурации, который может быть изменен в какой-то момент, я думаю, что лучше всего очистить вручную, чтобы ваши тесты не вызывали проблем в будущем.
Майкл Ликури
0

Другой подход - использовать 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с указанным условием.

Уоллес Сидри
источник
1
Что автору вопрос как отключить console.log на тестировании. Это решение не оптимально.
Эрик
Для копировальных аппаратов: замените ===на в !==соответствии с вашими потребностями. Я использую этот подход в течение многих лет, и он работает безупречно, но я вношу изменения в соответствии со своими потребностями.
Wallace Sidhrée
Не отвечает на вопрос.
Майкл Орил,
Это хакерское решение, которое нельзя настраивать. Что если отключить только для определенного теста, а не для другого?
Jhonatan