使用Jest测试覆盖控制台.log



我使用以下代码过滤一些消息:

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;
});

相关内容

最新更新