玩笑: 如何模拟控制台时,它是由第三方库使用?

我试图模仿控制台。警告/错误,但我不能。我使用第三方库调用控制台,在里面警告。我需要测试一下它叫什么名字。在我的测试案例中,我试图存根控制台。警告,但它没有帮助。在那之后,我试图手动模拟控制台,它也没有工作。

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

80289 次浏览

必须使用 global来访问全局上下文中的对象

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

或使用在 19.0.0中加入的 jest.spyOn

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

使用 jest.spyOn()mockRestore()

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

接受的答案不会恢复原来的 console.warn(),并将“损害”同一文件中的其他测试(如果在其他测试或正在测试的代码中使用了 console.warn())。

仅供参考,如果在测试文件中使用 console.warn = jest.fn(),它不会影响其他测试文件(例如,console. wart 将返回到其他测试文件中的原始值)。

建议: 您可以在 afterEach()/afterAll()中调用 consoleWarnMock.mockRestore(),以确保即使一个测试崩溃,它也不会损害同一文件中的其他测试(例如,确保同一文件中的测试是完全隔离的)。

完整的例子:

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

你不能写

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

因为它不会恢复原来的 console.warn()

/! 使用 mockImplementationOnce(),你仍然需要拨打 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

你也可以写:

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

您可以尝试以下操作,测试并请确保在 jest 配置文件中有 clearMockstrue

test('it should console warn a message', ()=>{
jest.spyOn(global.console, 'warn').mockImplementation();


console.warn('my error');
expect(console.warn).toBeCalledTimes(1)
expect(console.warn).toBeCalledWith('my error');
})
module.exports = {
...
clearMocks: true,
...
}