基于事件的单元测试因“ done()被多次调用”而失败”

问题描述 投票:4回答:1

我有一个使用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,但这将导致测试失败,并显示超时而不是我想要的错误。

javascript mocha eventemitter
1个回答
3
投票

您的测试失败,因为您在测试完成后仍在监听事件。

在您的下一个测试中,客户端会再次触发该事件,因此将再次调用先前(并已完成)的测试事件处理程序。

这里有两个选项:

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

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

once

请注意,您可能需要使用describe('test', () => { it('should work', done => { const finish = err => { done(err) client.removeListener('success', finish) client.removeListener('error', finish) } client.on('success', result => { result.should.equal('foo') // rest of tests for result... finish() }) client.on('error', finish) }) }) off而不是removeEventListener-您的removeListener用于解除监听器绑定的任何方法。

使用client处理程序:

或者,您可以使用once方法来监听事件。顾名思义,此处理程序仅触发一次,因此以后无需手动删除侦听器。

once

警告:此方法有一个警告。它不允许您测试once是否实际触发事件仅一次的极端情况。如果once错误地触发describe('test', function () { it('should work', done => { client.once('success', result => { result.should.equal('foo') // rest of tests for result... done() }) client.once('error', done) }) }) 不止一次,您的测试也将错误地成功。

© www.soinside.com 2019 - 2024. All rights reserved.