如何在nodejs上用mochaunit testing控制台输出
考虑下面的示例javascript代码:
function privateFunction (time) { if (time < 12) { console.log('Good morning'); } if (time >= 12 && time <19) { console.log('Good afternoon'); } else { console.log('Good night!'); } };
我应该怎样使用mocha(可能是sinonjs)对nodejs进行unit testing,注意到这是一个在模块内调用的私有函数? 我需要传入参数,并检查函数是否正确logging到控制台。
我可以做同样的console.warn
和console.error
?
我更喜欢mocha-sinon
不是“纯”的,因为它与摩卡很好地结合在一起。
例:
var expect = require('chai').expect; require('mocha-sinon'); // Function to test, can also be in another file and as long as it's // being called through some public interface it should be testable. // If it's not in any way exposed/exported, testing will be problematic. function privateFunction (time) { if (time < 12) { console.log('Good morning'); } if (time >= 12 && time <19) { console.log('Good afternoon'); } else { console.log('Good night!'); } } describe('privateFunction()', function() { beforeEach(function() { this.sinon.stub(console, 'log'); }); it('should log "Good morning" for hours < 12', function() { privateFunction(5); expect( console.log.calledOnce ).to.be.true; expect( console.log.calledWith('Good morning') ).to.be.true; }); it('should log "Good afternoon" for hours >= 12 and < 19', function() { privateFunction(15); expect( console.log.calledOnce ).to.be.true; expect( console.log.calledWith('Good afternoon') ).to.be.true; }); it('should log "Good night!" for hours >= 19', function() { privateFunction(20); expect( console.log.calledOnce ).to.be.true; expect( console.log.calledWith('Good night!') ).to.be.true; }); });
一个潜在的问题:一些摩卡记者也使用console.log
,所以存根的testing可能不会产生任何输出。
有一个解决方法,但是它不是理想的,因为它会使用来自privateFunction()
的输出散布Mocha输出。 如果这不是问题,用这个replacebeforeEach()
:
beforeEach(function() { var log = console.log; this.sinon.stub(console, 'log', function() { return log.apply(log, arguments); }); });
无视这是一个私人function的事实,我会采取几个步骤; 重构我的代码以更好地分离关注点,并利用testing双打进行分离。
-
把外面的所有副作用带到自己的模块里(这里的副作用是写给控制台):
out.js
function log (message) { console.log(message); }; module.exports = {log};
app.js
const {log} = require('out'); function greeter (time) { if (time < 12) { log('Good morning'); } if (time >= 12 && time < 19) { log('Good afternoon'); } else { log('Good night!'); } }; module.exports = {greeter};
-
使用一些模块代理/间谍,就像proxyquire在testing时replace整个写入器:
app.spec.js
describe('output writers', function(){ const fakeOut = { log: sinon.spy(), }; const app = proxyquire('./app', { 'out': fakeOut }); it('should log to the fake out', function(){ app.greeter(15); assert(fakeOut.log.calledOnce); }); });