我使用以下代码过滤一些消息:
const consoleLog = console.log;
console.log = (...args) => {
if (args.length === 0 || typeof args[0] !== 'string' || !args[0].includes('[HMR]')) {
consoleLog.apply(console, args);
}
};
如何测试此函数的控制台输出?通常,我只会模拟console.log
,但在这种情况下,它被上面的代码覆盖,所以我不能这样做。
或者根本不搞砸原来的console.log
。
const consoleLog = (...args) => {
if (args.length === 0 || typeof args[0] !== 'string' || !args[0].includes('[HMR]')) {
console.log.apply(console, args);
}
};
然后在应用程序代码中专门使用consoleLog
。
这种间接的好处:
- 它更安全。你从不给原始
console.log
打补丁。 - 它更面向未来。如果您稍后从
console.log
切换到第三方日志记录框架,则不必调整所有日志记录代码。
但是,如果您有意配置超出您控制范围的代码(第 3 方(使用console.log
,这当然不适用于这种情况。
使用这种方法,对于单元测试,请按照estus的答案中的建议监视console.log
(从未修改过(。
猴子修补全局 API 通常不是一个好的做法。最好公开原始函数以防万一,至少出于测试目的。
如果它更灵活,测试它会更容易,例如,修补的代码可以用环境变量控制,以防需要回退到原始行为:
console._logOriginal = console.log;
console.log = (...args) => {
if (
!process.env.NO_HMR_SPAM ||
(args.length === 0 || typeof args[0] !== 'string' || !args[0].includes('[HMR]'))
) {
console._logOriginal(...args);
}
};
在这种情况下,可以监视console._logOriginal
。
否则,应在评估此模块之前备份原始console.log
,在此之前不应导入:
const consoleLogOriginal = console.log;
it('...', async () => {
const consoleLogSpy = jest.spyOn(console, 'log');
await import('moduleThatManglesConsole');
console.log('[HMR]');
expect(consoleLogSpy).not.toHaveBeenCalled();
console.log('');
expect(consoleLogSpy).toHaveBeenCalledWith('');
})
afterEach(() => {
console.log = consoleLogOriginal;
});