我正在nodejs
为我的网络应用构建一个日志记录模块。我希望能够使用mocha
测试我的模块将正确的消息输出到terminal
。我一直在环顾四周,但没有找到任何明显的解决方案来检查这一点。我找到了
process.stdout.on('data', function (){})
但未能使其发挥作用。有人有什么建议吗?
答案 0 :(得分:16)
process.stdout
永远不会发出'data'
个事件,因为它不是可读的流。如果您感到好奇,可以在node stream documentation中阅读所有相关信息。
据我所知,挂钩或捕获process.stdout
或process.stderr
的最简单方法是将process.stdout.write
替换为您想要的功能。超级hacky,我知道,但是在测试场景中你可以使用钩子之前和之后确保它被解开,所以它或多或少是无害的。因为无论如何它写入底层流,如果你不解开它,它不是世界末日。
function captureStream(stream){
var oldWrite = stream.write;
var buf = '';
stream.write = function(chunk, encoding, callback){
buf += chunk.toString(); // chunk is a String or Buffer
oldWrite.apply(stream, arguments);
}
return {
unhook: function unhook(){
stream.write = oldWrite;
},
captured: function(){
return buf;
}
};
}
你可以在像这样的摩卡测试中使用它:
describe('console.log', function(){
var hook;
beforeEach(function(){
hook = captureStream(process.stdout);
});
afterEach(function(){
hook.unhook();
});
it('prints the argument', function(){
console.log('hi');
assert.equal(hook.captured(),'hi\n');
});
});
这里有一个警告:摩卡记者打印到标准输出。据我所知,当示例(it('...',function(){})
)函数正在运行时,它们不会这样做,但如果示例函数是异步的,则可能会遇到麻烦。我会看看能否找到更多相关信息。
答案 1 :(得分:11)
我已经尝试过jjm的回答并遇到了我怀疑是由于我的程序异步行为造成的问题。
我通过使用sinon库的github上的cli找到了一个解决方案。
要测试的示例代码:
/* jshint node:true */
module.exports = Test1;
function Test1(options) {
options = options || {};
}
Test1.prototype.executeSync = function() {
console.log("ABC");
console.log("123");
console.log("CBA");
console.log("321");
};
Test1.prototype.executeASync = function(time, callback) {
setTimeout(function() {
console.log("ABC");
console.log("123");
console.log("CBA");
console.log("321");
callback();
}, time);
};
摩卡测试:
/* jshint node:true */
/* global describe:true, it:true, beforeEach:true, afterEach:true, expect:true */
var assert = require('chai').assert;
var expect = require('chai').expect;
var sinon = require("sinon");
var Test1 = require("../test");
var test1 = null;
describe("test1", function() {
beforeEach(function() {
sinon.stub(console, "log").returns(void 0);
sinon.stub(console, "error").returns(void 0);
test1 = new Test1();
});
afterEach(function() {
console.log.restore();
console.error.restore();
});
describe("executeSync", function() {
it("should output correctly", function() {
test1.executeSync();
assert.isTrue(console.log.called, "log should have been called.");
assert.equal(console.log.callCount, 4);
assert.isFalse(console.log.calledOnce);
expect(console.log.getCall(0).args[0]).to.equal("ABC");
expect(console.log.getCall(1).args[0]).to.equal("123");
expect(console.log.args[2][0]).to.equal("CBA");
expect(console.log.args[3][0]).to.equal("321");
});
});
describe("executeASync", function() {
it("should output correctly", function(done) {
test1.executeASync(100, function() {
assert.isTrue(console.log.called, "log should have been called.");
assert.equal(console.log.callCount, 4);
assert.isFalse(console.log.calledOnce);
expect(console.log.getCall(0).args[0]).to.equal("ABC");
expect(console.log.getCall(1).args[0]).to.equal("123");
expect(console.log.args[2][0]).to.equal("CBA");
expect(console.log.args[3][0]).to.equal("321");
done();
});
});
});
});
我提供上述内容,因为它演示了使用异步调用,它处理控制台和错误输出,检查方法更有用。
我应该注意到,我提供了两种获取传递给控制台的方法,console.log.getCall(0).args[0]
和console.log.args[0][0]
。第一个参数是写入控制台的行。随意使用您认为合适的内容。
答案 2 :(得分:3)
另外两个有助于此的库是test-console和intercept-stdout我没有使用过inter-stdout,但是这里是你可以用test-console做的。
var myAsync = require('my-async');
var stdout = require('test-console').stdout;
describe('myAsync', function() {
it('outputs something', function(done) {
var inspect = stdout.inspect();
myAsync().then(function() {
inspect.restore();
assert.ok(inspect.output.length > 0);
done();
});
});
});
注意:您必须使用Mocha的异步api。没有电话done()
会吞下摩卡的测试信息。