Jest: як знущатись над консоллю, коли вона використовується сторонньою бібліотекою?


84

Я намагаюся знущатися з console.warn / error, але не можу. Я використовую сторонню бібліотеку, яка викликає console.warn всередині неї. Мені потрібно перевірити, називався він це чи ні. У моєму тестовому випадку я намагався заглушити console.warn, але це не допомогло. Після цього я намагався знущатись над консоллю вручну, теж не вийшло.

console.warn = jest.fn();
testSchema('/app/components/Users/UserItem/UserItemContainer.js');
expect(console.warn).toBeCalled();

не працював

console.warn = jest.fn();
testSchema('/app/components/Users/UserItem/UserItemContainer.js');
console.warn('error');
expect(console.warn).toBeCalled();

справді працював. Але я все ще бачу console.warn node_modules/babel-relay-plugin/lib/getBabelRelayPlugin.js:138в терміналі. Хто-небудь може мені допомогти?

Відповіді:


145

Ви повинні використовувати globalдля доступу до об’єктів у глобальному контексті

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

або використовувати jest.spyOnдоданий в19.0.0

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

2
Так, хлопці, це працює. Але одне - вам потрібно зажадати lib після того, як ви оголосите global.console. Я зробив це неправильно. Я вимагав свою бібліотеку і після цього оголосив глобальним. Дякую.
Errorpro

2
Цікаво, як це ніде не задокументовано на веб-сайті Jest. Я шукаю і не можу знайти нічого, що пояснює це.
Леонардо

2
з typecript
Gerard Brull

8
просто так, щоб усі усвідомлювали. global.console = {...}буде придушувати помилку , поки jest.spyOn(...)не буде. Ви вирішуєте, чи хочете ви пригнічувати помилки у своїх тестах.
a11smiles

38
Я віддаю перевагу jest.spyOn(...)тому, що це легше прибирати, і я використовую TypeScript, але також хотів придушити помилки у виведенні, як згадує @ a11smiles. Тож я використав, jest.spyOn(global.console, "warn").mockImplementation(() => {})котрий заважає шпигунові console.warn
зазивати

73

Використовуйте jest.spyOn()та spy.mockRestore().

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

Прийнята відповідь не відновлює оригінал console.warn()і "скомпрометує" інші тести всередині того ж файлу (якщо console.warn()використовується в інших тестах або коді, що тестується).

FYI, якщо ви використовуєте console.warn = jest.fn()в тестовому файлі, це не вплине на інші тестові файли (наприклад, console.warn повернеться до початкового значення в інших тестових файлах).

Порада: ви можете зателефонувати spy.mockRestore()всередину afterEach()/, afterAll()щоб бути впевненим, що навіть якщо тест аварійно завершиться, це не призведе до компрометації інших тестів із того самого файлу (наприклад, гарантує, що тести всередині того самого файлу повністю ізольовані).

Повний приклад:

const spy = 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(spy).toHaveBeenCalledTimes(2); // Another syntax
expect(console.warn).toHaveBeenLastCalledWith('message2');
expect(spy).toHaveBeenLastCalledWith('message2'); // Another syntax
expect(spy.mock.calls).toEqual([['message1'], ['message2']]);
expect(console.warn.mock.calls).toEqual([['message1'], ['message2']]);
spy.mockRestore(); // IMPORTANT
//console.warn.mockRestore(); // Another syntax

console.warn('message3'); // Will be displayed (not mocked anymore)
expect(spy).toHaveBeenCalledTimes(0); // Not counting anymore
expect(spy.mock.calls).toEqual([]);
//expect(console.warn.mock.calls).toEqual([]); // Crash

Ви не можете писати

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

оскільки це не відновить оригінал console.warn().

/! \ З mockImplementationOnce()вами все одно потрібно буде зателефонувати spy.mockRestore():

// /!\
const spy = jest.spyOn(console, 'warn').mockImplementationOnce(() => {});
console.warn('message1'); // Won't be displayed (mocked)
expect(console.warn).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledTimes(1); // Another syntax
expect(console.warn).toHaveBeenLastCalledWith('message1');
expect(spy).toHaveBeenLastCalledWith('message1'); // Another syntax
expect(spy.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 counting
expect(spy.mock.calls).toEqual([['message1'], ['message2']]);
expect(console.warn.mock.calls).toEqual([['message1'], ['message2']]);

spy.mockRestore(); // IMPORTANT
//console.warn.mockRestore(); // Another syntax
console.warn('message3'); // Will be displayed (not mocked anymore)
expect(spy).toHaveBeenCalledTimes(0); // Not counting anymore
expect(spy.mock.calls).toEqual([]);
//expect(console.warn.mock.calls).toEqual([]); // Crash

Ви також можете написати:

const assert = console.assert;
console.assert = jest.fn();
...
console.assert = assert;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.