笑话。如何在第三方库使用时模拟控制台?

时间:2016-12-19 13:45:52

标签: javascript unit-testing tdd jestjs

我正在尝试模拟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。任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:77)

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

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

或使用jest.spyOn

中添加的19.0.0
jest.spyOn(global.console, 'warn')

答案 1 :(得分:7)

使用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;