在调用异步函数的mocha测试中如何避免超时错误:超过2000ms的超时

时间:2013-05-17 10:40:59

标签: node.js mocha chai

在我的节点应用程序中,我使用mocha来测试我的代码。在使用mocha调用许多异步函数时,我收到超时错误(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();
        });

    });

});

7 个答案:

答案 0 :(得分:326)

您可以在运行测试时设置超时:

mocha --timeout 15000

或者您可以通过编程方式为每个套件或每个测试设置超时:

describe('...', function(){
  this.timeout(15000);

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

有关详细信息,请参阅docs

答案 1 :(得分:79)

我发现只是增加超时的“解决方案”掩盖了这里真正发生的事情,这是

  1. 您的代码和/或网络呼叫速度太慢(为了获得良好的用户体验,应该低于100毫秒)
  2. 断言(测试)失败,并且在Mocha能够对其进行操作之前,有些东西正在吞下错误。
  3. 当Mocha没有收到来自回调的断言错误时,您通常会遇到#2。这是由一些其他代码吞噬堆栈中的异常引起的。 处理此问题的正确方法是修复代码而不是吞下错误

    当外部代码吞噬您的错误时

    如果它是一个你无法修改的库函数,你需要捕获断言错误并自己将它传递给Mocha。您可以通过在try / catch块中包装断言回调并将任何异常传递给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);
        }
      });
    });
    

    这个样板文件当然可以被提取到一些实用功能中,使测试更加令人赏心悦目:

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

    加速网络测试

    除此之外,我建议您接受有关开始使用测试存根进行网络调用的建议,以便在不依赖于正常运行的网络的情况下通过测试。使用Mocha,Chai和Sinon测试可能看起来像这样

    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's nise docs

答案 2 :(得分:7)

有点晚了,但是将来有人可以使用...您可以通过以下方法更新package.json中的脚本来增加测试超时:

"scripts": { "test": "test --timeout 10000" //Adjust to a value you need }

使用命令test

运行测试

答案 3 :(得分:1)

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

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

所以这就是它在不能正常工作时的样子:

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

这可以使用匿名函数

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

希望它可以帮助某人,我的配置如上: (nodejs:8.4.0,npm:5.3.0,mocha:3.3.0)

答案 4 :(得分:0)

我的问题不是发回响应,所以挂起了。如果您使用的是Express,请确保针对要测试的路由执行了res.send(data),res.json(data)或您想使用的任何api方法。

答案 5 :(得分:0)

如果您使用的是箭头功能:

it('should do something', async () => {
  // do your testing
}).timeout(15000)

答案 6 :(得分:0)

请确保解决/拒绝测试用例中使用的承诺,无论是间谍还是存根,都要确保它们解决/拒绝。