226

在我的节点应用程序中,我使用 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();
        });

    });

});
4

7 回答 7

368

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

mocha --timeout 15000

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

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

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

有关更多信息,请参阅文档

于 2013-05-17T11:02:02.190 回答
86

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

  1. 您的代码和/或网络调用太慢了(应该低于 100 毫秒以获得良好的用户体验)
  2. 断言(测试)失败,并且在 Mocha 能够对错误采取行动之前,某些东西正在吞噬错误。

当 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 的nise文档

于 2013-12-09T11:50:25.463 回答
22

如果您使用箭头函数:

it('should do something', async () => {
  // do your testing
}).timeout(15000)
于 2019-11-28T17:16:12.663 回答
7

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

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

使用命令运行测试test

于 2018-08-21T15:58:11.553 回答
1

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

因为没有任何承诺被拒绝,所以对于在描述块内失败的不同测试,我一直收到这个错误

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

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

这可以使用匿名函数

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

希望它对某人有所帮助,我的上述配置:(nodejs:8.4.0,npm:5.3.0,mocha:3.3.0)

于 2017-09-24T17:12:06.907 回答
0

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

于 2020-04-20T09:46:17.973 回答
0

我的问题是没有发回响应,所以它挂了。如果您使用 express,请确保 res.send(data)、res.json(data) 或您想要使用的任何 api 方法都已针对您正在测试的路线执行。

于 2019-08-01T23:09:29.160 回答