我用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()
})
})
请注意,您可能需要使用off
或removeEventListener
而不是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
,那么您的测试也会错误地成功。我不知道你现在该如何优雅地处理这件事,但欢迎发表评论。