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

sac*_*hin 190 mocha.js node.js 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();
        });

    });

});
Run Code Online (Sandbox Code Playgroud)

And*_*ren 334

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

mocha --timeout 15000
Run Code Online (Sandbox Code Playgroud)

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

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

  it('...', function(done){
    this.timeout(15000);
    setTimeout(done, 15000);
  });
});
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅文档.

  • `TypeError:当使用`"mocha"时,this.timeout不是函数`:"^ 3.5.0"` (24认同)
  • 仅供参考:不鼓励将箭头功能传递给摩卡.http://mochajs.org/#arrow-functions (5认同)
  • 上面的链接不鼓励使用箭头功能.它只是说你只需要知道他们做了什么,这样你就不会在需要访问上下文时搞砸了.我从不需要上下文,因为依赖超时是脆弱的,我的所有测试都在几毫秒内完成,但在使用sinon-test时我遇到了同样的问题.仍有99%的时间使用lambdas. (4认同)
  • @adi你确定你没有使用箭头功能吗?关于async /等待它在文档中所以应该工作(并且与使用promises相同).听起来像另一个问题. (4认同)
  • 较短的版本是```-t```.如果你使用mocha-test从grunt任务运行mocha,那么选项对象```options:{timeout:15000}```也支持这个. (3认同)

oli*_*ren 80

我发现只是增加超时的"解决方案"模糊了这里真正发生的事情,也就是说

  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);
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

加速网络测试

除此之外,我建议您接受关于开始使用测试存根进行网络调用的建议,以使测试通过,而不必依赖于正常运行的网络.使用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;
    });

});
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅Sinon的nise文档.


luk*_*s_o 17

如果您使用箭头函数:

it('should do something', async () => {
  // do your testing
}).timeout(15000)
Run Code Online (Sandbox Code Playgroud)


小智 7

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

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

使用以下命令运行测试 test