【问题标题】:Detecting console.log() calls检测 console.log() 调用
【发布时间】:2011-11-06 23:51:56
【问题描述】:

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

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

【问题讨论】:

    标签: javascript jquery tdd error-logging


    【解决方案1】:

    console.log 不会记录已记录的消息,也不会发出您可以侦听的任何事件。您的测试不可能直接验证其来自 JavaScript 的输出。相反,您的测试代码需要将 console.log 替换为 mock 实现,该实现会跟踪日志消息以供以后验证。

    Mocking 是大多数 JavaScript 测试框架都支持的常见功能。例如,the Jest test framework provides a jest.spyOn function 将给定方法替换为模拟实现,该模拟实现在将参数传递给原始实现之前记录每个调用 in a .mock property 的参数。每次测试后,您可能需要调用 jest.clearAllMocks() 来重置下一次测试的记录参数列表,或使用 the equivalent clearMocks: true config option

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

    【讨论】:

    • 太棒了。如此简单,但我不会想到。
    • 当您向console.log 提供多个参数时,这无法处理,它会丢弃除第一个以外的所有参数。
    • @nh2 真的!固定。
    【解决方案2】:

    所以解决方案不错,但如果您正在寻找高性能记录器,请尝试 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/

    【讨论】:

    • 如何检查日志中是否存在某些内容?
    【解决方案3】:

    如果您使用的是 Jasmine,那就太简单了:

    it('is my test', function () {
        spyOn(console, 'log');
        // do your stuff that should log something
        expect(console.log).toHaveBeenCalledWith('something');
    });
    

    前往Jasmine docs了解更多信息。

    【讨论】:

    • 或者,如果使用 Jest(本质上是在 Jasmine 上构建或关闭),只需将 spyOn... 行替换为 console.log = jest.fn();
    【解决方案4】:

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

    开始测试之前 -

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

    运行测试后,如有必要 -

    console.log = originalLog
    

    【讨论】:

      【解决方案5】:

      可能最简单的方法是使用 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(),以便您的测试运行器仍然能够记录有关失败断言的信息。

      【讨论】:

        猜你喜欢
        • 2012-05-26
        • 1970-01-01
        • 2014-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-27
        相关资源
        最近更新 更多