【发布时间】:2011-11-06 23:51:56
【问题描述】:
我正在尝试为使用console.log() 将消息写入JavaScript 控制台的调试方法编写测试用例。测试必须检查消息是否已成功写入控制台。我正在使用 jQuery。
有没有办法在console.log() 上附加一个钩子或以其他方式检查是否已将消息写入控制台,或者对如何编写测试用例有任何其他建议?
【问题讨论】:
标签: javascript jquery tdd error-logging
我正在尝试为使用console.log() 将消息写入JavaScript 控制台的调试方法编写测试用例。测试必须检查消息是否已成功写入控制台。我正在使用 jQuery。
有没有办法在console.log() 上附加一个钩子或以其他方式检查是否已将消息写入控制台,或者对如何编写测试用例有任何其他建议?
【问题讨论】:
标签: javascript jquery tdd error-logging
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 提供多个参数时,这无法处理,它会丢弃除第一个以外的所有参数。
所以解决方案不错,但如果您正在寻找高性能记录器,请尝试 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 );
【讨论】:
如果您使用的是 Jasmine,那就太简单了:
it('is my test', function () {
spyOn(console, 'log');
// do your stuff that should log something
expect(console.log).toHaveBeenCalledWith('something');
});
前往Jasmine docs了解更多信息。
【讨论】:
spyOn... 行替换为 console.log = jest.fn();。
只需将您自己的函数附加到console.log。 在您的页面上,加载完所有内容后,
开始测试之前 -
var originalLog = console.log;
console.log = function(msg){
alert('my .log hook received message - '+msg);
//add your logic here
}
运行测试后,如有必要 -
console.log = originalLog
【讨论】:
可能最简单的方法是使用 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(),以便您的测试运行器仍然能够记录有关失败断言的信息。
【讨论】: