2015-11-02 63 views
2

我想写一个摩卡测试,它传递流错误,但如果流结束时没有错误失败。测试应通过流错误,成功失败

检测错误不成问题,但始终调用完成处理程序,即使强制错误输出流。在此代码中,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

+1

你看看https://github.com/mochajs/mocha/wiki/Spies? – Sonata

+0

感谢您的指针。这应该工作,除了我的实际用例是公共包,所以我宁愿避免添加任何新的依赖关系。 – joemaller

+0

也许这个特定流的实现有错误吗?流从哪里来? – Ben

回答

0

编辑

我想我们都同意是什么使这一问题具有挑战性的是,多个完成()被调用执行(两个事件射击)。如果摩卡看到多个完成的呼叫,测试将自动失败。

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

Sinon是一个有用的libray,它提供了“间谍”,告诉我们什么时候发生事件。

检查了这一点: 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. 
    }); 
    }); 
}; 

它不是一个纯粹的本地解决方案,因为它依赖于兴农。不过,我认为它仍然是一个很好的选择。

+1

完成的处理程序从来没有被调用,除非有错误,那么在反向测试用例上这将如何失败?如果流*不会抛出错误,则测试应明确失败。 – joemaller

+0

我明白你的意思。我会查看代码,看看我能否修改答案。 –

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); 
相关问题