检测console.log()调用

14

我正在尝试为一种使用console.log()将消息写入JavaScript控制台的调试方法编写测试用例。该测试必须检查消息是否已成功写入控制台。我正在使用jQuery。

有没有一种方法可以附加钩子到console.log(),或者以其他方式检查消息是否已写入控制台,或者对于如何编写测试用例还有其他建议?

5个回答

27

console.log并不会记录已经输出的信息,也不会发出事件以供监听。因此,无法直接在JavaScript中验证其输出结果。相反,你需要用一个模拟实现(mock implementation)来替换console.log,以便保留日志消息以供之后验证。

模拟是大多数JavaScript测试框架都支持的一个常见特性。例如,Jest测试框架提供了一个jest.spyOn函数,它可以用一个模拟实现替换给定方法,记录每个调用的参数在一个.mock属性中,然后将它们传递给原始实现。在每个测试之后,你可能需要调用jest.clearAllMocks()来重置下一次测试的记录参数列表,或者使用等效的clearMocks: true配置选项

function saySomething() {
  console.log("Hello World");
}
jest.spyOn(console, 'log');

test("saySomething says hello", () => {
  expect(console.log.mock.calls.length).toBe(0);
  saySomething();
  expect(console.log.mock.calls.length).toBe(1);
  expect(console.log.mock.calls[0][0]).toBe("Hello World");
});

afterEach(() => {
  jest.clearAllMocks();
});

如果您没有使用测试框架(您可能应该使用),您可以自己创建一个简单的模拟。

function saySomething() {
  console.log("Hello World");
}
function testSomething() {
  // Replace console.log with stub implementation.
  const originalLog = console.log;
  const calls = [];
  console.log = (...args) => {
    calls.push(args);
    originalLog(...args);
  };

  try {
    console.assert(calls.length == 0);
    saySomething();
    console.assert(calls.length == 1);
    console.assert(calls[0][0] == "Hello World");
  } catch (error) {
    console.error(error);
  } finally {
    // Restore original implementation after testing.
    console.log = originalLog;
  }
}

1
太棒了。如此简单,但我想不到。 - JJJ
这个并不能处理当你给 console.log 多个参数时,它会丢弃除第一个以外的所有参数。 - nh2
@nh2 确实没错!已修复。 - Jeremy

10

如果您在寻找一款高效的日志记录器,可以尝试使用Paul Irish的 log()

如果那个太高效了,您可以考虑使用类似以下的东西。

var console = window.console,
    _log = console ? console.log : function(){};

_log.history = [];

console.log = function( ){
  _log.history.push.apply( _log.history, arguments );
  _log.apply( console, arguments );
}

使用方法

console.log('I','have','an','important','message');
//Use native one instead
_log.call( console, _log.history );

http://jsfiddle.net/BeXdM/


我该如何检查日志中是否存在某些内容? - Seif El-Din Sweilam

9
如果你使用Jasmine,那么它非常简单:
it('is my test', function () {
    spyOn(console, 'log');
    // do your stuff that should log something
    expect(console.log).toHaveBeenCalledWith('something');
});

请到Jasmine文档了解更多信息。


1
或者,如果使用 Jest(它本质上是建立在 Jasmine 之上或之外的),只需将 spyOn... 行替换为 console.log = jest.fn(); - Andrew Willems

7

只需将您自己的函数附加到console.log。在页面加载完毕后,在您的页面上,

开始测试之前 -


var originalLog = console.log;
console.log = function(msg){
  alert('my .log hook received message - '+msg); 
  //add your logic here
}

运行测试后,如有必要 -

console.log = originalLog

0

可能最简单的方法是使用NPM包std-mocks

根据他们的文档:

var stdMocks = require('std-mocks');
 
stdMocks.use();
process.stdout.write('ok');
console.log('log test\n');
stdMocks.restore();
 
var output = stdMocks.flush();
console.log(output.stdout); // ['ok', 'log test\n']

注意:在进行断言之前,请确保先执行stdMocks.restore(),这样您的测试运行器仍然能够记录有关失败断言的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接