测试应传递流错误,成功失败

时间:2015-11-02 14:55:22

标签: javascript node.js mocha should.js

我正在尝试编写一个传递流错误的mocha测试,但如果流结束没有错误则会失败。

检测错误没有问题,但总是调用终结处理程序,即使流被强制错误输出也是如此。在此代码中,error处理程序的should.exist(err)断言正常工作,但finish处理程序仍然会引发错误。

describe('catch stream errors', function() {
  it('should throw an error', function(done) {
    var stream = failStream();

    stream.on('error', function(err) {
      should.exist(err);
      done();
    })

    stream.on('finish', function() {
      done(new Error('Why does this still run?'));
    });

    stream.write();
    stream.end();
  })
})

一种似乎有点像黑客攻击的解决方法是将errored变量放在处理程序之上,然后在error处理程序中将其翻转并检查finish中的值处理程序。似乎应该有一个更好的方法来处理这个问题。

var errored = false;

stream.on('error', function(err) {
  should.exist(err);
  errored = true;
  done();
})

stream.on('finish', function() {
  if (!errored) {
    done(new Error('Error suppressed'));
  }
});

全部要点here

2 个答案:

答案 0 :(得分:0)

修改

我认为我们都同意这个问题的挑战在于正在执行多个Done()调用(两个事件触发)。如果Mocha看到多个完成的调用,则测试将自动失败。

看起来如果我们能够证明错误事件发生,我们的测试将是合理的。

Sinon是一个有用的图书馆,提供"间谍"告诉我们何时发出事件。

检查一下: https://github.com/mochajs/mocha/wiki/Spies

var stream = require('stream');
var util = require('util');
var should = require('should');


// Writer
util.inherits(Writer, stream.Writable);

function Writer(opt) {
   stream.Writable.call(this, opt);
}

Writer.prototype._write = function(data, encoding, callback) {
  console.log(data.toString());
  // This will cause the stream to always return error
  callback(new Error('FAIL STREAM'));
};


var test =

module.exports.run =  function() {

  describe('catch stream errors', function() {
    it('should throw an error', function() {
      // setup the stream that always fails
      var stream = new Writer();

      // Initialize the spies
      var errorSpy = sinon.spy();
      var finishSpy = sinon.spy();

      // When the stream events fire, 
      // callback the respective spies
      stream.on('error', errorSpy);
      stream.on('finish', finishSpy);

      // Write to the stream, I setup the stream to 
      // always return an error when something is written.

      stream.write('hello');
      stream.end();

      console.log('errorSpy Called: '+ errorSpy.called);
      console.log('finishSpy Called: '+ finishSpy.called);

      errorSpy.called.should.equal(true);  // Mocha Test Fails If Error Event Was Not Emitted.
      finishSpy.called.should.equal(true); // Mocha Test Fails If Finish Never Happened.
    });
  });
};

它不是纯粹的原生解决方案,因为它依赖于Sinon。但是,我认为它仍然是一个很好的选择。

答案 1 :(得分:0)

更优雅的解决方案是从错误侦听器中删除完成侦听器。这类似于节点lib/stream源文件中的cleanup方法。

// Refactor out the listeners
var onerror = function(err) {
  should.exist(err);
  this.removeListener('finish', onfinish);
  done();
};

var onfinish = function() {
  done(new Error('Expected stream to throw an error.'));
};

stream.on('error', onerror);
stream.on('finish', onfinish);