web-dev-qa-db-ja.com

非同期関数を呼び出しながらモカテストでタイムアウトを回避する方法Error:2000msのタイムアウトを超えました

私のノードアプリケーションでは、私は自分のコードをテストするためにモカを使っています。モカを使用して多くの非同期関数を呼び出している間、私はタイムアウトエラー(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();
        });

    });

});
184
sachin

テスト実行時にタイムアウトを設定できます。

mocha --timeout 15000

または、各スイートまたは各テストのタイムアウトをプログラムで設定することもできます。

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

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

詳しくは docs をご覧ください。

328

タイムアウトを増やすだけの「解決策」が、実際に起こっていることを覆い隠していることがわかりました。

  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 docs をご覧ください。

79
oligofren

少し遅れましたが、将来誰かがこれを使用できるようになります。package.jsonのスクリプトを次のように更新することで、テストのタイムアウトを長くすることができます。

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

コマンドtestを使用してテストを実行します。

7
Daniel Mbeyah

私にとって問題は、実際にはdescribe関数です。これは、arrow関数が提供されると、mochaにタイムアウトを見逃させ、一貫して動作しません。 (ES6を使用)

describeブロック内で失敗したさまざまなテストに対して、このエラーが常に発生するという約束は拒否されなかったため、

正しく動作していないときにこのように見えるので、これは:

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

これは無名関数を使って機能します

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

それが誰かに役立つことを願って、上記のための私の設定:(nodejs:8.4.0、npm:5.3.0、mocha:3.3.0)

1
syberkitten

私の問題は応答を返送しなかったため、ハングしていました。エクスプレスを使用している場合は、res.send(data)、res.json(data)、または使用するapiメソッドがテストするルートに対して実行されることを確認してください。

0
il0v3d0g