基于事件的单元测试失败,并显示"done() called multiple times"



我用mocha:设置了一个简单的异步回调测试

describe('test', function () {
it('should not work', function(done) {
client.on('success', function () {
return done('client saw success message but should have errored');
});
client.on('error', function (err) {
return done();
});
});
});

其想法是客户端执行一些异步操作,并且应该接收一个错误事件。如果它接收到任何其他内容,那么测试应该失败。

不幸的是,mocha一直在抱怨:

done() called multiple times

我做了各种各样的事情来证实这不是真的。例如,我尝试在成功处理程序中的done之前抛出错误,在控制到达成功处理程序时进行日志记录,等等。

我如何在不告诉我正在调用done两次的情况下运行此测试?我会抛出一个错误,而不是用错误消息调用done,但这会导致测试失败,并导致超时,而不是我想要的错误。

您的测试失败,因为在测试已完成。

完成的测试不会自动删除事件侦听器。

在下一次测试中,您将再次启动该事件,但之前的测试事件由于侦听器仍在侦听事件,因此会再次调用它们。由于在该测试完成时CCD_ 6已经被调用,他们再次开火,因此你得到了done was called multiple times的错误。

这里有几个选项:

  • 您可以在每次测试后使用命名函数来删除事件侦听器
  • 您可以使用once侦听器

通过命名函数删除事件侦听器:

describe('test', () => {  
it('should work', done => {
const finish = err => {
done(err)
client.removeListener('success', finish)
client.removeListener('error', finish)
}
client.on('error', finish)    
client.on('success', result => {
result.should.equal('foo')
// rest of tests for result...
finish()
})
client.fireEvent()
})  
})

请注意,您可能需要使用offremoveEventListener而不是removeListener——无论client使用哪种方法来删除侦听器。

使用once侦听器:

或者,您可以使用once侦听器来侦听事件。顾名思义,这个处理程序只触发一次,因此之后不需要手动删除侦听器。

describe('test', function () {  
it('should work', done => {
client.once('error', done)
client.once('success', result => {
result.should.equal('foo')
// rest of tests for result...
done()
})
client.fireEvent()
})
})

警告:这些方法有一个重要的警告。它们不允许您测试边缘情况,即client是否真的只触发事件一次。如果client错误地多次触发success,那么您的测试也会错误地成功。我不知道你现在该如何优雅地处理这件事,但欢迎发表评论。

最新更新