在我的节点应用程序中,我使用mocha来测试我的代码。当使用mocha调用许多异步函数时,我得到超时错误(错误:超过2000ms超时)。我该如何解决这个问题?

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

    });

});

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

mocha --timeout 15000

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

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

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

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


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

你的代码和/或网络调用太慢了(为了获得良好的用户体验,应该低于100毫秒) 断言(测试)正在失败,在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文档了解更多信息。


对我来说,问题在于描述函数, 哪一个当提供了箭头功能,导致摩卡错过了 超时,并且行为不一致。(使用ES6)

由于没有承诺被拒绝,我一直得到这个错误,不同的测试在描述块内失败

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

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

这需要匿名函数

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

希望对大家有所帮助,我的配置如下: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)


有点晚了,但将来有人可以用这个…您可以通过更新包中的脚本来增加测试超时。Json格式:

"脚本":{ "test": "test——timeout 10000" //调整为你需要的值 }

使用test命令运行测试


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


如果你使用箭头函数:

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

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