121 votes

Jest : comment simuler la console lorsqu'elle est utilisée par une bibliothèque tierce ?

J'essaie de simuler console.warn/error mais je n'y arrive pas. J'utilise une bibliothèque tierce qui appelle console.warn en son sein. J'ai besoin de tester s'il a été appelé ou non. Dans mon cas de test, j'ai essayé de simuler console.warn mais cela n'a pas aidé. Après cela, j'ai essayé de simuler la console manuellement, mais cela n'a pas fonctionné non plus.

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

n'a pas fonctionné

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

a fonctionné. Mais je vois toujours console.warn node_modules/babel-relay-plugin/lib/getBabelRelayPlugin.js:138 dans le terminal. Quelqu'un peut-il m'aider ?

178voto

Andreas Köberle Points 16453

Vous devez utiliser global pour accéder aux objets dans le contexte global

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

ou utiliser jest.spyOn ajouté dans 19.0.0

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

0 votes

Vous êtes sûr ? Ça ne marche toujours pas. global.console = { warn: jest.fn(), error: jest.fn(), }; testSchema('/app/components/Users/UserItem/UserItemContainer‌​.js'); expect(global.console.warn).toBeCalled();

0 votes

Je l'utilise pour tester la fonctionnalité de journalisation, son expect(console.warn).toBeCalled() pour tester l'appel.

3 votes

Oui, ça marche. Mais une chose est que vous devez exiger la librairie après avoir déclaré global.console. Je l'ai mal fait. J'ai exigé ma librairie et après j'ai déclaré global. Merci.

127voto

tanguy_k Points 1475

Utilisez jest.spyOn() y spy.mockRestore() .

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

La réponse acceptée ne rétablit pas l'original console.warn() et "compromettra" les autres tests à l'intérieur du même fichier (si console.warn() est utilisé à l'intérieur des autres tests ou du code testé).

Pour info, si vous utilisez console.warn = jest.fn() dans un fichier de test, cela n'affectera pas les autres fichiers de test (par exemple console.warn reprendra sa valeur originale dans les autres fichiers de test).

Conseil : vous pouvez appeler spy.mockRestore() à l'intérieur de afterEach() / afterAll() pour être sûr que même si un test se plante, il ne compromettra pas les autres tests du même fichier (c'est-à-dire que les tests à l'intérieur d'un même fichier sont totalement isolés).

Exemple complet :

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

Vous ne pouvez pas écrire

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

parce que ça ne restaurera pas l'original console.warn() .

/!\N- Avec mockImplementationOnce() vous devrez toujours appeler 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

Vous pouvez également écrire :

const assert = console.assert;
console.assert = jest.fn();
...
console.assert = assert;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X