【问题标题】:Event-based unit tests fail with "done() called multiple times"基于事件的单元测试因“done() 多次调用”而失败
【发布时间】:2018-04-25 10:05:25
【问题描述】:

我用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,但这会导致测试失败并出现超时而不是我想要的错误。

【问题讨论】:

  • 测试完成后,您需要从该测试中的client 中删除事件侦听器。您可能在以下测试中重用相同的 client 对象,这会导致先前测试的事件侦听器重新触发
  • 令人困惑的是,这是我编写的唯一测试(当我添加它时,我没有看到任何日志显示“成功”被触发)。不过我会试一试。
  • 我会为你写一个答案

标签: javascript mocha.js eventemitter


【解决方案1】:

您的测试失败了,因为您在 测试结束

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

在您的下一个测试中,您将再次触发该事件,但之前的测试事件 再次调用侦听器,因为它们仍在侦听事件。 由于测试完成时已经调用了done, 他们再次开火,因此您会收到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,您的测试也会错误地成功。我不确定你现在如何优雅地处理这个问题,但欢迎 cmets。

【讨论】:

  • 你是对的——事实证明“错误”处理程序被调用了两次。我清除了处理程序并且它起作用了。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-07-06
  • 1970-01-01
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多