Jest: Кращий спосіб вимкнути консоль при модульних тестах


91

Цікаво, чи є кращий спосіб вимкнути консольні помилки в межах певного тесту 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здається, лише працюю з цим .

Дякую!

Відповіді:


125

Для конкретного специфікаційного файлу файл Андреаса досить хороший. Нижче налаштування подавить 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
Знущання global.console- справді простий спосіб, і це можна зробити за допомогою будь-якого налаштованого setupFilesAfterEnv . Остерігайтеся знущатися над усіма власними методами consoleоб’єкта, інакше у вас можуть виникнути інші несподівані помилки.
Vadorequest

49

Оскільки кожен тестовий файл працює у власному потоці, немає необхідності його відновлювати, якщо ви хочете відключити його для всіх тестів в одному файлі. З тієї ж причини ви також можете просто писати

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

1
Дякую за інформацію з цього приводу. Це має сенс :) Я шукав спосіб зробити це таким чином лише в межах певного тесту без необхідності його відновлення (спочатку я думав, що це поведінка за замовчуванням), але я думаю, beforeEach робить трюк.
Apidcloud

46

Якщо ви хочете зробити це лише для певного тесту:

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

1
це чудово!
sheriff_paul

20

Я виявив, що відповідь вище re: придушення console.logу всіх тестових наборах викликало помилки при виклику будь-яких інших consoleметодів (наприклад warn, error), оскільки воно замінювало весь глобальний consoleоб'єкт.

Цей дещо подібний підхід спрацював у мене з Jest 22+:

package.json

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

жарт / setup.js

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

За допомогою цього методу console.logзнущаються лише над іншими consoleметодами.


6

Для мене більш зрозумілим / чистим способом (читачеві потрібно мало знати 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 тощо
Michael Oryl

1
@ michael-liquori, чому вам потрібно перезапустити console.log? Думаю, після кожного опису
висміювання

2
@Jhonatan Я не думаю, що це стає зрозумілим після кожного опису, хоча я не тестував цього нещодавно, щоб бути впевненим. Відповідно до пошукових документів існує параметр clearMocksі і resetMocksконфігурація, але обидва вони за замовчуванням false, і жоден з них насправді не відновлює початкову реалізацію, навіть якщо встановлено значення true. І, враховуючи, що це варіант конфігурації, який може бути змінений в якийсь момент, я вважаю, що найкращою практикою буде очищення вручну, щоб переконатися, що ваші тести не спричинять проблем у майбутньому.
Michael Liquori

-1

Інший підхід - використання 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 під час тестування. Це рішення не є оптимальним.
Ерік

Для копірувальників: замініть ===на !==відповідно до ваших потреб. Я використовую цей підхід роками, і він працює бездоганно, але я роблю коригування відповідно до своїх потреб.
Уоллес Сідре

Не відповідає на актуальне запитання.
Michael Oryl

Це хакерське рішення, яке не можна налаштувати. Що робити, якщо вимкнути лише для певного тесту, а не іншого?
Йонатан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.