2016-11-12 78 views
1

我使用mocha来针对外部Web服务运行一些集成测试。我使用superagent-promise作为请求/响应处理,并且我使用expect作为我的断言库。使用superagent + promises的摩卡测试超时而不是以'expect'失败

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

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. 

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

回答

2

这是已知的问题吗?

这实际上不是问题。

问题是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)抛出的错误。

+0

就是这样!我是JavaScript的新承诺 - 我没有意识到catch(),但它完美地工作。 –

2

在你的情况下,超时发生,因为完成的回调从不被调用,要么是因为http请求没有失败,要么期望失败,所以它抛出了断言错误。

摩卡处理正确的(承诺返回)异步测试,所以不要使用完成的回调,它会导致混淆与承诺混淆。相反地​​返回承诺:

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); 
    }); 
}); 
+0

“* ...或者是因为http请求没有失败...... *”OP明确指出,他对代码的唯一更改是将expect(err.status).toBe(401)'更改为'expect(err .STATUS).toBe(200)'。基于这个前提,问题在于抛出的断言错误会阻止'.then'承诺内的代码的执行 - 在OP的代码中被承诺吞噬的错误(正如我的回答中所述)。 – rabbitco

+0

@rabbitco这就是为什么你在处理promise时不应该使用'done',并让Mocha正确处理它们的原因。 – robertklep

+0

@robertklep:同意 – rabbitco