简体   繁体   中英

Detecting console.log() calls

I'm trying to write a test case for a debugging method that writes messages to the JavaScript console using console.log() . The test has to check that the message has been successfully written to the console. I'm using jQuery.

Is there a way to attach a hook to console.log() or otherwise check that a message has been written to the console, or any other suggestions on how to write the test case?

console.log doesn't keep a record of messages that are logged, or emit any events that you could listen for. It's not possible for your tests to directly verify its output from JavaScript. Instead, your test code will need to replace console.log with a mock implementation that does keep track of log messages for later verification.

Mocking is a common feature supported by most JavaScript test frameworks. For example, the Jest test framework provides a jest.spyOn function which replaces a given method with a mock implementation that records the arguments for each call in a .mock property before passing them on to the original implementation. After each test you may want to call jest.clearAllMocks() to reset the recorded argument lists for the next test, or use 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();
});

If you're not using a test framework (you probably should), you can create a simple mock yourself.

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

So not bad solutions, but if you're looking for a high powered logger try Paul Irish's log()

If that's too high powered, you can get by with something like this.

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

Usage

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

http://jsfiddle.net/BeXdM/

If you're using Jasmine, it's dead simple:

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

Head to Jasmine docs for more info.

Just attach your own function to console.log. On your page, after everything loads,

Before starting tests -


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

After running tests, if necessary -

console.log = originalLog

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM