Выход приложения Mocha Monitor

Я создаю модуль регистрации для своего веб-приложения в nodejs. Я бы хотел проверить с помощью mocha, что мой модуль выводит правильные сообщения в terminal. Я смотрю вокруг, но не нашел очевидных решений, чтобы проверить это. Я нашел

process.stdout.on('data', function (){})

но не смогли заставить это работать. кто-нибудь имеет какие-либо советы?

Ответ 1

process.stdout никогда не будет генерировать события 'data', потому что это не читаемый поток. Вы можете прочитать все об этом в node потоковой документации, если вам интересно.

Насколько я знаю, самый простой способ привязки или захвата process.stdout или process.stderr заключается в замене process.stdout.write на функцию, которая делает то, что вы хотите. Супер хаки, я знаю, но в сценарии тестирования вы можете использовать до и после крючков, чтобы убедиться, что он отцеплен, поэтому он более или менее безопасен. Поскольку он все равно пишет основному потоку, это не конец света, если вы все равно не отцепите его.

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

Вы можете использовать его в тестах mocha следующим образом:

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

Здесь предостережение: репортеры mocha печатают на стандартный вывод. Они, насколько мне известно, не делают этого, пока выполняются функции (it('...',function(){})), но вы можете столкнуться с проблемами, если ваши примерные функции асинхронны. Я посмотрю, смогу ли я больше узнать об этом.

Ответ 2

Я попытался ответить jjm и имел проблемы, которые, как я подозреваю, был связан с поведением асинхронных программ.

Я нашел решение через cli на github, который использует библиотеку sinon.

Пример кода для проверки:

/* 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]. Первым параметром является строка, написанная на консоли. Не стесняйтесь использовать то, что считаете нужным.

Ответ 3

Две другие библиотеки, которые помогают с этим: test-console и intercept-stdout Я не использовал intercept-stdout, но вот как вы можете это сделать с помощью тестовой консоли.

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 async api. Нет вызова done() будет проглатывать тестовые сообщения mocha.