如何在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.warnconsole.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); }); });