web-dev-qa-db-fra.com

Comment tester la sortie de la console avec mocha sur nodejs?

Prenez en compte l'exemple de code Javascript suivant ci-dessous:

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 devrais-je tester cela sur les nodejs en utilisant mocha (et éventuellement sinonjs), sachant qu'il s'agit d'une fonction privée appelée à l'intérieur d'un module? Je dois passer l'argument et vérifier si la fonction enregistre la bonne chose à la console.

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

23
kemelzaidan

Je préfère mocha-sinon / "plain" sinon car il s'intègre bien avec Mocha.

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 reporters de Mocha utilisent également console.log; les tests qui en résultent ne génèrent donc aucun résultat.

Il existe une solution de contournement, mais elle n'est pas idéale non plus, car elle entremêle la sortie Mocha et la sortie de privateFunction(). Si ce n'est pas un problème, remplacez beforeEach() par ceci:

beforeEach(function() {
  var log = console.log;
  this.sinon.stub(console, 'log', function() {
    return log.apply(log, arguments);
  });
});
28
robertklep

en ignorant le fait que c'est une fonction privée, je prendrais quelques mesures; refactoriser mon code pour une meilleure séparation des problèmes et utiliser cette séparation avec des tests en double.

  • prenez tous les effets secondaires extérieurs à leurs propres modules (l’effet secondaire écrit ici dans la console):

    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};
    
  • utilisez un module proxy/spy, comme proxyquire pour remplacer le rédacteur complet lors des tests:

    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);
      });
    });
    
3
Eliran Malka

Si votre but est only de tester la sortie de la console, je suggérerais d'utiliser à la place des stubs/espions, etc., des appels de méthode: 

  • test-console

  • surveillez stdout/stderr à la place, vous pouvez utiliser les idées de ceci Gist

0
Angelos Pikoulas