Beim Mokka-Testen beim Aufrufen der asynchronen Funktion wird vermieden, dass das Zeitlimit vermieden wird. Fehler: Das Zeitlimit von 2000 ms wurde überschritten

200

In meiner Knotenanwendung verwende ich Mokka, um meinen Code zu testen. Beim Aufrufen vieler asynchroner Funktionen mit Mokka wird ein Timeout-Fehler ( Error: timeout of 2000ms exceeded.) angezeigt . Wie kann ich das beheben?

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

    });

});
Sachin
quelle
ist es ein Integrationstest? Es ist viel Zeit für einen Test - vielleicht sollten Sie Stubs in Betracht ziehen - github.com/thlorenz/proxyquire könnte Ihnen helfen.
Surui
@ Gurui danke ich werde darauf schauen
Sachin
Darf ich empfehlen, Versprechen für asynchrone Inhalte zu verwenden und sie dann zu testen, ist ein Kinderspiel mit Chai als Versprechen
Krym

Antworten:

344

Sie können entweder das Zeitlimit festlegen, wenn Sie Ihren Test ausführen:

mocha --timeout 15000

Oder Sie können das Zeitlimit für jede Suite oder jeden Test programmgesteuert festlegen:

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

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

Weitere Informationen finden Sie in den Dokumenten .

Andreas Hultgren
quelle
3
kürzere Version ist -t. Wenn Sie Mokka-Test verwenden, um Mokka von einer Grunzaufgabe auszuführen, wird dies auch im Optionsobjekt unterstützt options:{timeout:15000}.
Svassr
5
Zu Ihrer Information: Es wird davon abgeraten, Pfeilfunktionen an Mocha zu übergeben. mochajs.org/#arrow-functions
c0ming
4
Pfeilfunktionen werden im obigen Link nicht entmutigt. Es heißt nur, dass Sie nur wissen müssen, was sie tun, damit Sie es nicht vermasseln, wenn Sie auf den Kontext zugreifen müssen. Ich brauche den Kontext nie, da das Verlassen auf Timeouts fragil ist und alle meine Tests in wenigen ms ausgeführt werden, aber ich stoße bei der Verwendung von sinon-test auf dasselbe Problem. Verwenden Sie immer noch 99% der Zeit Lambdas.
Oligofren
26
TypeError: this.timeout is not a functionbei der Verwendung"mocha": "^3.5.0"
Junior Mayhé
5
@adi Bist du sicher, dass du keine Pfeilfunktionen verwendest? In Bezug auf Async / Warten ist es in den Dokumenten enthalten, sollte also funktionieren (und ist das gleiche wie das Verwenden von Versprechungen). Klingt aber nach einer anderen Frage.
Andreas Hultgren
80

Ich finde, dass die "Lösung", nur die Zeitüberschreitungen zu erhöhen, verdeckt, was hier wirklich vor sich geht

  1. Ihr Code und / oder Ihre Netzwerkanrufe sind viel zu langsam (sollten für eine gute Benutzererfahrung unter 100 ms liegen).
  2. Die Behauptungen (Tests) schlagen fehl und etwas verschluckt die Fehler, bevor Mocha darauf reagieren kann.

Normalerweise stoßen Sie auf Nummer 2, wenn Mocha keine Bestätigungsfehler von einem Rückruf erhält. Dies wird durch einen anderen Code verursacht, der die Ausnahme weiter oben im Stapel verschluckt. Der richtige Weg, um damit umzugehen, besteht darin, den Code zu korrigieren und den Fehler nicht zu verschlucken .

Wenn externer Code Ihre Fehler verschluckt

Falls es sich um eine Bibliotheksfunktion handelt, die Sie nicht ändern können, müssen Sie den Assertionsfehler abfangen und selbst an Mocha übergeben. Sie tun dies, indem Sie Ihren Assertion-Rückruf in einen Try / Catch-Block einschließen und alle Ausnahmen an den erledigten Handler übergeben.

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

Diese Boilerplate kann natürlich in eine Utility-Funktion extrahiert werden, um den Test für das Auge ein wenig angenehmer zu gestalten:

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

Beschleunigung von Netzwerktests

Abgesehen davon schlage ich vor, dass Sie die Ratschläge zur Verwendung von Teststubs für Netzwerkanrufe lesen, um Tests zu bestehen, ohne auf ein funktionierendes Netzwerk angewiesen zu sein. Mit Mocha, Chai und Sinon könnten die Tests ungefähr so ​​aussehen

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

});

Siehe Sinon der nisedocs für weitere Informationen.

Oligofren
quelle
Ich habe eine riesige Reihe von Tests und habe gerade alle Versprechen in meinen Spezifikationen durchgesehen, um sicherzustellen, dass sie alle done()am Ende des Versprechens anrufen. Ich verspotte bereits die Netzwerkanrufe mit Angulars $httpBackend, aber kein Glück. Es scheint nicht sehr pragmatisch, jede einzelne Spezifikation mit einem Try-Catch zu versehen. Irgendwelche anderen Vorschläge? Vielen Dank!
Gustavo Matias
@GustavoMatias Sie haben tatsächlich nicht erwähnt, was Ihr Problem ist, sondern nur angegeben, dass dies keine Lösung für alles ist, mit dem Sie Probleme haben. Bitte erläutern Sie :-) Scheitern Ihre Tests nicht schnell genug? Scheitern sie manchmal, aber Sie möchten wissen warum? Schwer zu erraten, was Sie erreichen wollen.
Oligofren
hi @oligofren! Das war in der Tat nicht die beste Erklärung. Eine ausführlichere Erklärung meines Problems finden Sie hier stackoverflow.com/questions/34510048/… danke!
Gustavo Matias
"Im Allgemeinen besteht die sauberste (aber hässlichste) Möglichkeit, mit diesem Problem umzugehen, darin, Ihren Code mit einem Versuch / Fang zu versehen und alle Ausnahmen an den erledigten Handler zu übergeben." Nein, das ist überhaupt nicht der sauberste Weg. Bei weitem nicht. Am saubersten ist es, Code zu schreiben, der keine Ausnahmen verschluckt. Jedes Mal, wenn ich jemanden gesehen habe, der sich beschwert hat, dass Mocha keinen fehlgeschlagenen Test entdeckt hat, lag das daran, dass etwas die Ausnahme verschluckt hat. Hinzufügen von einem try.... catch...Arbeiten rund um den Fehler in dem im Test befindlichen Code nicht fix es.
Louis
@ Louis, Sie haben vielleicht Recht mit dem Warum hier, aber ich kann es nicht aus heiterem Himmel überprüfen. Auf jeden Fall haben die Leute ein Problem damit, dass Mocha anscheinend nicht in der Lage ist, Fehler zu erkennen, und dies ist eine Möglichkeit, damit umzugehen. Ihr Ansatz geht davon aus, dass der Code, der den Fehler verschluckt, keine Bibliotheksfunktion oder ähnliches ist. In diesem Fall wäre er nicht so einfach zu lösen.
Oligofren
7

Ein bisschen spät, aber jemand kann dies in Zukunft verwenden ... Sie können Ihr Test-Timeout erhöhen, indem Sie die Skripte in Ihrer package.json wie folgt aktualisieren:

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

Führen Sie Ihre Tests mit dem Befehl aus test

Daniel Mbeyah
quelle
Hat für mich gearbeitet! Danke!
RayLoveless
5

Wenn Sie Pfeilfunktionen verwenden:

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

Für mich war das Problem tatsächlich die Beschreibungsfunktion, die bei Bereitstellung einer Pfeilfunktion dazu führt, dass Mokka das Timeout verpasst und sich nicht konsistent verhält. (Mit ES6)

Da kein Versprechen abgelehnt wurde, wurde dieser Fehler ständig für verschiedene Tests angezeigt, die innerhalb des Beschreibungsblocks fehlgeschlagen sind

So sieht es aus, wenn es nicht richtig funktioniert:

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

und dies funktioniert mit der anonymen Funktion

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

Hoffe es hilft jemandem, meine Konfiguration für die oben genannten: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)

Syberkätzchen
quelle
0

Mein Problem bestand darin, die Antwort nicht zurückzusenden, daher hing sie. Wenn Sie Express verwenden, stellen Sie sicher, dass res.send (Daten), res.json (Daten) oder eine beliebige API-Methode, die Sie verwenden möchten, für die zu testende Route ausgeführt wird.

il0v3d0g
quelle
0

Stellen Sie sicher, dass Sie die in den Testfällen verwendeten Versprechen auflösen / ablehnen, sei es Spione oder Stubs. Stellen Sie sicher, dass sie auflösen / ablehnen.

Kavigun
quelle