Lors des tests de moka lors de l'appel de la fonction asynchrone, comment éviter le délai d'attente Erreur: dépassement du délai d'attente de 2000 ms

200

Dans mon application de nœud, j'utilise mocha pour tester mon code. Lors de l'appel de nombreuses fonctions asynchrones à l'aide de mocha, j'obtiens une erreur de temporisation ( Error: timeout of 2000ms exceeded.). Comment puis-je résoudre ça?

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
la source
est-ce un test d'intégration? il faut beaucoup de temps pour qu'un test s'exécute - vous devriez peut-être envisager des talons - github.com/thlorenz/proxyquire pourrait vous aider.
surui
@surui merci je vais regarder ça
sachin
Puis-je recommander d'utiliser des promesses pour des trucs asynchrones et de les tester est alors un jeu d'enfant avec Chai comme promesse
Krym

Réponses:

344

Vous pouvez soit définir le délai d'expiration lors de l'exécution de votre test:

mocha --timeout 15000

Ou vous pouvez définir le délai d'expiration pour chaque suite ou chaque test par programme:

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

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

Pour plus d'informations, consultez la documentation .

Andreas Hultgren
la source
3
la version plus courte est -t. si vous utilisez mocha-test pour exécuter mocha à partir de la tâche grunt, cela est également pris en charge dans l'objet options options:{timeout:15000}.
svassr
5
Pour info: le passage des fonctions fléchées à Mocha est déconseillé. mochajs.org/#arrow-functions
c0ming
4
Les fonctions fléchées ne sont pas déconseillées dans le lien ci-dessus. Cela dit simplement que vous avez juste besoin de savoir ce qu'ils font pour ne pas bousiller lorsque vous avez besoin d'accéder au contexte. Je n'ai jamais besoin du contexte, car compter sur les délais d'attente est fragile, et tous mes tests s'exécutent en quelques ms, mais je rencontre le même problème lorsque j'utilise sinon-test. Utilisez toujours des lambdas 99% du temps.
oligofren
26
TypeError: this.timeout is not a functionlors de l'utilisation"mocha": "^3.5.0"
Junior Mayhé
5
@adi êtes-vous sûr de ne pas utiliser les fonctions fléchées? En ce qui concerne async / wait, c'est dans la documentation, donc ça devrait marcher (et c'est la même chose que d'utiliser des promesses). Cela ressemble à une autre question.
Andreas Hultgren
80

Je trouve que la "solution" consistant simplement à augmenter les délais d'attente obscurcit ce qui se passe réellement ici, qui est soit

  1. Votre code et / ou vos appels réseau sont beaucoup trop lents (devraient être inférieurs à 100 ms pour une bonne expérience utilisateur)
  2. Les assertions (tests) échouent et quelque chose avale les erreurs avant que Mocha ne puisse y donner suite.

Vous rencontrez généralement # 2 lorsque Mocha ne reçoit pas d'erreurs d'assertion d'un rappel. Cela est dû à un autre code avalant l'exception plus haut dans la pile. La bonne façon de résoudre ce problème est de corriger le code et de ne pas avaler l'erreur .

Quand le code externe avale vos erreurs

Dans le cas où il s'agit d'une fonction de bibliothèque que vous ne pouvez pas modifier, vous devez intercepter l'erreur d'assertion et la transmettre vous-même à Mocha. Pour ce faire, vous encapsulez votre rappel d'assertion dans un bloc try / catch et passez toutes les exceptions au gestionnaire 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);
    }
  });
});

Ce passe-partout peut bien sûr être extrait dans une fonction d'utilité pour rendre le test un peu plus agréable à l'œil:

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

Accélérer les tests de réseau

En dehors de cela, je vous suggère de suivre les conseils pour commencer à utiliser des talons de test pour les appels réseau pour faire passer les tests sans avoir à compter sur un réseau qui fonctionne. En utilisant Mocha, Chai et Sinon, les tests pourraient ressembler à ceci

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

});

Voir les nisedocuments de Sinon pour plus d'informations.

oligofren
la source
J'ai une énorme suite de tests et je viens de passer toutes les promesses dans mes spécifications pour m'assurer qu'ils appellent tous done()à la fin de la promesse et je me moque déjà des appels réseau en utilisant Angular's $httpBackend, mais pas de chance. Envelopper chaque spécification avec un try-catch ne semble pas très pragmatique. D'autres suggestions? Merci!
Gustavo Matias
@GustavoMatias En fait, vous n'avez pas mentionné quel est votre problème, vous venez de dire que ce n'est pas une solution à ce que vous rencontrez des problèmes. Veuillez élaborer :-) Vos tests n'échouent-ils pas assez rapidement? Ils échouent parfois, mais vous aimeriez savoir pourquoi? Difficile de deviner ce que vous avez l'intention de réaliser.
oligofren
salut @oligofren! ce n'était pas la meilleure explication en effet. Il y a une explication plus détaillée de mon problème ici stackoverflow.com/questions/34510048/… merci!
Gustavo Matias
"En général, la manière la plus propre (mais la plus laide) de traiter ce problème est d'envelopper votre code avec un try / catch et de passer toutes les exceptions au gestionnaire done." Non, ce n'est pas du tout le moyen le plus propre. Pas de loin. La façon la plus simple est d'écrire du code qui n'allonge pas les exceptions. Chaque fois que j'ai vu quelqu'un se plaindre que Mocha ne détectait pas un test qui avait échoué, c'était parce qu'il y avait quelque chose qui avalait l'exception. Ajout d' un try.... catch...travaux autour du bogue dans le code en cours de test plutôt que de fixer elle.
Louis
@Louis, vous avez peut-être raison sur le pourquoi ici, mais je ne peux pas le vérifier à l'improviste. de toute façon, les gens ont un problème avec Mocha qui ne semble pas pouvoir détecter une erreur, et c'est une façon de le gérer. votre approche donnée suppose que le code avalant l'erreur n'est pas une fonction de bibliothèque ou similaire, auquel cas il ne serait pas si facilement résolu.
oligofren
7

Un peu tard mais quelqu'un peut l'utiliser à l'avenir ... Vous pouvez augmenter votre délai de test en mettant à jour les scripts dans votre package.json avec ce qui suit:

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

Exécutez vos tests à l'aide de la commande test

Daniel Mbeyah
la source
A travaillé pour moi! Merci!
RayLoveless
5

Si vous utilisez les fonctions fléchées:

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

Pour moi, le problème était en fait la fonction de description, qui, lorsqu'elle est fournie avec une fonction de flèche, fait que le moka manque le délai d'attente et ne se comporte pas de manière cohérente. (Utilisation d'ES6)

comme aucune promesse n'a été rejetée, j'obtenais cette erreur tout le temps pour différents tests qui échouaient dans le bloc de description

donc à quoi cela ressemble quand il ne fonctionne pas correctement:

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

et cela fonctionne en utilisant la fonction anonyme

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

J'espère que cela aide quelqu'un, ma configuration pour ce qui précède: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)

syberkitten
la source
0

Mon problème ne renvoyait pas la réponse, elle était donc suspendue. Si vous utilisez express, assurez-vous que res.send (données), res.json (données) ou quelle que soit la méthode api que vous souhaitez utiliser est exécutée pour l'itinéraire que vous testez.

il0v3d0g
la source
0

Assurez-vous de résoudre / rejeter les promesses utilisées dans les cas de test, que ce soit des espions ou des talons, assurez-vous qu'ils résolvent / rejettent.

kavigun
la source