摩卡监视器应用程序输出

jos*_*son 12 mocha.js node.js

我正在为我的网络应用程序构建一个日志记录模块nodejs.我希望能够测试使用mocha我的模块输出正确的消息给terminal.我一直在环顾四周,但没有找到任何明显的解决方案来检查这一点.我已经找到

process.stdout.on('data', function (){})
Run Code Online (Sandbox Code Playgroud)

但无法让这个工作.有人有什么建议吗?

jjm*_*jjm 16

process.stdout永远不会发出'data'事件,因为它不是一个可读的流.如果您很好奇,可以在节点流文档中阅读所有相关内容.

据我所知,最简单的方法,以挂钩或捕获process.stdout或者process.stderr是更换process.stdout.write与你想要做什么的功能.超级hacky,我知道,但是在测试场景中你可以使用钩子之前和之后确保它被解开,所以它或多或少是无害的.因为无论如何它写入底层流,如果你不解开它,它不是世界末日.

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;
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

你可以在像这样的摩卡测试中使用它:

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');
  });
});
Run Code Online (Sandbox Code Playgroud)

这里有一个警告:摩卡记者打印到标准输出.据我所知,当example(it('...',function(){}))函数正在运行时,它们不会这样做,但如果示例函数是异步的,则可能会遇到麻烦.我会看看能不能找到更多相关信息.


Met*_*kin 11

我试过jjm的答案,并且遇到了我怀疑是由于我的程序异步行为引起的问题.

我通过使用sinon库的github上的cli找到了一个解决方案.

要测试的示例代码:

/* 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);
};
Run Code Online (Sandbox Code Playgroud)

而摩卡测试:

/* 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();
      });

    });
  });
});
Run Code Online (Sandbox Code Playgroud)

我提供上面的内容,因为它演示了使用异步调用,它处理控制台和错误输出,并且检查方法更有用.

我应该注意到,我提供了两种方法来获取传递给控制台的内容,console.log.getCall(0).args[0]以及console.log.args[0][0].第一个参数是写入控制台的行.随意使用您认为合适的内容.

  • 这似乎是更好的答案,只因为它利用了常见的Sinon存根模式,因此可能比尝试捕获process.stdout或其他更容易理解.可能只是我,但...... (2认同)

ian*_*arz 7

对此有帮助的另外两个库是test-consoleintercept-stdout我没有使用过intercept-stdout,但这里是你如何使用test-console 来做到这一点。

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();
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

注意:必须使用 Mocha 的 async api。没有呼叫done()会吞下 mocha 的测试消息。