Шутка: как издеваться над консолью, когда она используется сторонней библиотекой?

Я пытаюсь mock 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 в терминале. Может кто-нибудь мне помочь?

Ответ 1

Вы должны использовать global доступ к объектам в глобальном контексте

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

или используйте jest.spyOn добавленный в 19.0.0

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

Ответ 2

Используйте jest.spyOn() и spy.mockRestore().

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

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

К вашему сведению, если вы используете 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;