javascript - Jest: hur man mockar console när det används av ett tredjepartsbibliotek?
Jag försöker mocka console.warn/error men jag kan inte. Jag använder ett tredjepartsbibliotek som anropar console.warn inuti det. Jag behöver testa om det anropades eller inte. I mitt testfall försökte jag stubba console.warn men det hjälpte inte. Efter det försökte jag mocka console manuellt, det fungerade inte heller.
console.warn = jest.fn();
testSchema('/app/components/Users/UserItem/UserItemContainer.js');
expect(console.warn).toBeCalled();
funkade inte
console.warn = jest.fn();
testSchema('/app/components/Users/UserItem/UserItemContainer.js');
console.warn('error');
expect(console.warn).toBeCalled();
gjorde arbete.
Men jag ser fortfarande console.warn node_modules/babel-relay-plugin/lib/getBabelRelayPlugin.js:138 i terminalen.
Svar #1
Du måste använda global för att få tillgång till objekt i det globala sammanhanget
global.console = {warn: jest.fn()}
expect(console.warn).toBeCalled()
eller använd jest.spyOn som lades till i 19.0.0
jest.spyOn(global.console, 'warn')
Svar #2
Använd jest.spyOn() och mockRestore().
const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation();
...
consoleWarnMock.mockRestore();
Det accepterade svaret återställer inte den ursprungliga console.warn() och kommer att "kompromettera" de andra testerna i samma fil (om console.warn() används i de andra testerna eller i koden som testas).
För din information, om du använder console.warn=jest.fn() i en testfil, kommer det inte att påverka andra testfiler (t.ex. kommer console.warn att återgå till sitt ursprungliga värde i de andra testfilerna).
Du kan kalla consoleWarnMock.mockRestore() inuti afterEach()/afterAll() för att vara säker på att även om ett test kraschar, kommer det inte att äventyra de andra testen från samma fil (t.ex. säkerställer att testen inuti samma fil är helt isolerade).
Fullständigt exempel:
const consoleWarnMock = 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(consoleWarnMock).toHaveBeenCalledTimes(2); // Another syntax
expect(console.warn).toHaveBeenLastCalledWith('message2');
expect(consoleWarnMock).toHaveBeenLastCalledWith('message2'); // Another syntax
expect(consoleWarnMock.mock.calls).toEqual([['message1'], ['message2']]);
expect(console.warn.mock.calls).toEqual([['message1'], ['message2']]);
consoleWarnMock.mockRestore(); // IMPORTANT
//console.warn.mockRestore(); // Another syntax
console.warn('message3'); // Will be displayed (not mocked anymore)
expect(consoleWarnMock).toHaveBeenCalledTimes(0); // Not counting anymore
expect(consoleWarnMock.mock.calls).toEqual([]);
//expect(console.warn.mock.calls).toEqual([]); // Crash
Du kan inte skriva
console.warn = jest.fn().mockImplementation();
...
console.warn.mockRestore();
eftersom det inte kommer att återställa den ursprungliga console.warn().
/!\ Med mockImplementationOnce() kommer du fortfarande behöva anropa consoleWarnMock.mockRestore():
// /!\
const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementationOnce(() => {});
console.warn('message1'); // Won't be displayed (mocked)
expect(console.warn).toHaveBeenCalledTimes(1);
expect(consoleWarnMock).toHaveBeenCalledTimes(1); // Another syntax
expect(console.warn).toHaveBeenLastCalledWith('message1');
expect(consoleWarnMock).toHaveBeenLastCalledWith('message1'); // Another syntax
expect(consoleWarnMock.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(consoleWarnMock.mock.calls).toEqual([['message1'], ['message2']]);
expect(console.warn.mock.calls).toEqual([['message1'], ['message2']]);
consoleWarnMock.mockRestore(); // IMPORTANT
//console.warn.mockRestore(); // Another syntax
console.warn('message3'); // Will be displayed (not mocked anymore)
expect(consoleWarnMock).toHaveBeenCalledTimes(0); // Not counting anymore
expect(consoleWarnMock.mock.calls).toEqual([]);
//expect(console.warn.mock.calls).toEqual([]); // Crash
Du kan också skriva:
const assert = console.assert;
console.assert = jest.fn();
...
console.assert = assert;
Du kan be Jest/Vitest att automatiskt återställa det ursprungliga tillståndet och implementationen av en mock före varje test tack vare restoreMocks: true istället för att manuellt anropa mySpy.mockRestore() i slutet av varje test.
