Comment faire pour tester l'Unité de sortie de la console avec mocha sur nodejs?

tenir compte de L'exemple suivant de code 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!'); }
};

Comment dois-je tester l'unité sur nodejs en utilisant mocha (et peut-être sinonjs), en remarquant qu'il s'agit d'une fonction privée appelée à l'intérieur d'un module? Je dois passer dans l'argument et vérifier si la fonction enregistre la bonne chose sur la console.

puis-je faire la même chose avec console.warn et console.error?

20
demandé sur peterh 2015-06-03 19:12:19

2 réponses

je préfère mocha-sinon sur le sinon "ordinaire" parce qu'il s'intègre bien avec le moka.

Exemple:

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

});

Un problème potentiel: certains Moka utiliser les reporters console.log aussi bien, donc les tests qui le talonnent peuvent ne pas donner de résultat.

il y a une solution de contournement, mais ce n'est pas idéal non plus parce qu'il va intercaler la sortie Mocha avec la sortie privateFunction(). Si ce n'est pas un problème, remplacez beforeEach() avec ceci:

beforeEach(function() {
  var log = console.log;
  this.sinon.stub(console, 'log', function() {
    return log.apply(log, arguments);
  });
});
26
répondu robertklep 2015-06-03 17:43:04

ignorant le fait qu'il s'agit d'une fonction privée, je prendrais quelques mesures; reformuler mon code pour une meilleure séparation des préoccupations, et utiliser cette séparation avec des doubles d'essai.

  • prendre tous les effets secondaires à l'extérieur de leurs propres modules (l'effet secondaire ici est d'écrire sur la console):

    .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};
    
  • utilisez un module proxy / spy, comme proxyquire pour remplacer l'ensemble de la sortie de l'écrivain lors de l'essai:

    app.specs.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);
      });
    });
    
2
répondu Eliran Malka 2017-10-30 23:30:45