在调用asynchronous函数的摩卡testing中如何避免超时错误:超过2000ms的超时

在我的节点应用程序中,我使用摩卡来testing我的代码。 当使用摩卡调用很多asynchronous函数时,我得到超时错误( Error: timeout of 2000ms exceeded. )。 我该如何解决这个问题?

 var module = require('../lib/myModule'); var should = require('chai').should(); describe('Testing Module', function() { it('Save Data', function(done) { this.timeout(15000); var data = { a: 'aa', b: 'bb' }; module.save(data, function(err, res) { should.not.exist(err); done(); }); }); it('Get Data By Id', function(done) { var id = "28ca9"; module.get(id, function(err, res) { console.log(res); should.not.exist(err); done(); }); }); }); 

运行testing时可以设置超时时间:

 mocha --timeout 15000 

或者你可以设置每个套件或每个testing编程的超时时间:

 describe('...', function(){ this.timeout(15000); it('...', function(done){ this.timeout(15000); setTimeout(done, 15000); }); }); 

欲了解更多信息,请参阅文档 。

我发现,增加超时的“解决scheme”掩盖了这里的真实情况,这也是

  1. 您的代码和/或networking调用速度太慢(应该低于100毫秒,以获得良好的用户体验)
  2. 断言(testing)失败了,有些事情在摩卡能够对他们采取行动之前吞噬了错误。

当Mocha没有收到来自callback的断言错误时,您通常会遇到#2。 这是由一些其他代码将exception进一步吞入栈中引起的。 处理这个问题的正确方法是修复代码,不要误吞错误

当外部代码吞噬你的错误

如果它是一个库函数,你不能修改,你需要抓住断言错误,并将其传递到摩卡自己。 你可以通过将你的断言callback包装在try / catch块中,并将任何exception传递给done处理程序。

 it('should not fail', function (done) { // Pass reference here! i_swallow_errors(function (err, result) { try { // boilerplate to be able to get the assert failures assert.ok(true); assert.equal(result, 'bar'); done(); } catch (error) { done(error); } }); }); 

这个样板当然可以提取到一些实用function,使testing更加美观一些:

 it('should not fail', function (done) { // Pass reference here! i_swallow_errors(handleError(done, function (err, result) { assert.equal(result, 'bar'); })); }); // reusable boilerplate to be able to get the assert failures function handleError(done, fn) { try { fn(); done(); } catch (error) { done(error); } } 

加快networkingtesting

除此之外,我build议你拿起关于开始使用networking调用testing存根的build议,以使testing通过,而不必依赖于function正常的networking。 使用摩卡,柴和锡诺testing可能看起来像这样

 describe('api tests normally involving network calls', function() { beforeEach: function () { this.xhr = sinon.useFakeXMLHttpRequest(); var requests = this.requests = []; this.xhr.onCreate = function (xhr) { requests.push(xhr); }; }, afterEach: function () { this.xhr.restore(); } it("should fetch comments from server", function () { var callback = sinon.spy(); myLib.getCommentsFor("/some/article", callback); assertEquals(1, this.requests.length); this.requests[0].respond(200, { "Content-Type": "application/json" }, '[{ "id": 12, "comment": "Hey there" }]'); expect(callback.calledWith([{ id: 12, comment: "Hey there" }])).to.be.true; }); }); 

请参阅Sinon的nise docs了解更多信息。

对于我来说,问题实际上是描述函数,当提供箭头函数时,它会导致摩卡错过超时,并且行为不一致。 (使用ES6)

因为没有承诺被拒绝,我得到这个错误一直在不同的testing,在描述块内失败

所以这看起来如何不正常工作:

 describe('test', () => { assert(...) }) 

这个工作使用匿名函数

 describe('test', function() { assert(...) }) 

希望它有助于某人,我的configuration为:(nodejs:8.4.0,npm:5.3.0,摩卡:3.3.0)

对于asynchronous调用,我们必须使用完成的callback。 如果你通过它(),然后调用它也即完成(); 否则不pipe你增加多less时间,都会超时。 否则不要通过它。 如果情况并非如此,并且在testing用例中有很多处理,那么增加该值将会有所帮助。