Mocha 测试使用 superagent + promises 超时而不是失败 'expect'

Mocha tests using superagent + promises timeout rather than fail with 'expect'

我正在使用 mocha 到 运行 一些针对外部 Web 服务的集成测试。我使用 superagent-promise 作为 request/response 处理,我使用 expect 作为我的断言库。

对于其中一些测试,我需要将大量请求链接在一起,因此 promise 非常有帮助。但是我注意到我的测试现在因超时(并且没有错误消息)而不是错误消息本身而失败。举个简单的例子:

  it('[MESSAGES-1] cannot be posted without an auth token', function(done) {
    agent.post(config.webRoot + '/rooms/ABC/messages').send({
      content: 'This is a test!'
    }).end().then(function(res) {
      // Not expected
    }, function(err) {
      expect(err.status).toBe(401)
      done()
    })
  })

按预期工作并通过:

  Messages
    ✓ [MESSAGES-1] cannot be posted without an auth token

但是 如果我改变我的断言以期待不同的状态代码:

expect(err.status).toBe(200) // This should fail

然后测试失败并超时!

  1) Messages [MESSAGES-1] cannot be posted without an auth token:
     Error: timeout of 1000ms exceeded. Ensure the done() callback is being called in this test.

这是一个常见问题吗?有没有我可以做的解决方法或调整?我不想失去使用承诺的能力。

Is this a known issue?

这实际上不是问题。

问题是 expect(err.status).toBe(200) 抛出一个错误,该错误被吞没在 .then 中,导致代码永远无法到达 done()。您应该将代码重组为以下内容:

it('[MESSAGES-1] cannot be posted without an auth token', function(done) {
    agent.post(config.webRoot + '/rooms/ABC/messages').send({
      content: 'This is a test!'
    }).end()

    .then(function(res) {
      // Not expected
    }, function(err) {
      expect(err.status).toBe(401)
      done()
    })
    .catch(function(err) {
        done(err); //report error thrown in .then
    })
  })

这样您就可以捕获并报告 expect(err.status).toBe(200) 抛出的错误。

在您的情况下,超时发生是因为从未调用 done 回调,要么是因为 http 请求没有失败,要么是预期失败,因此它引发了断言错误。

Mocha 处理适当的(promise 返回)异步测试,所以不要使用 done 回调,当与 promise 混合时会造成混淆。 Return 诺言改为:

it('[MESSAGES-1] cannot be posted without an auth token', function() {
  return agent.post(config.webRoot + '/rooms/ABC/messages').send({
    content: 'This is a test!'
  }).end().then(function(res) {
    // here you must throw an error, because if the post didnt fail somehow, the test would be green because of no assertations and no promise rejection.
    throw new Error("Not expected");
  }, function(err) {
    expect(err.status).toBe(401);
  });
});