Nel test moka durante la chiamata della funzione asincrona come evitare il timeout Errore: timeout superato di 2000 ms


200

Nella mia applicazione nodo sto usando mocha per testare il mio codice. Durante la chiamata di molte funzioni asincrone tramite moka, viene visualizzato l'errore di timeout ( Error: timeout of 2000ms exceeded.). Come posso risolvere questo?

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

    });

});

è un test di integrazione? è un sacco di tempo per eseguire un test - forse dovresti considerare gli stub - github.com/thlorenz/proxyquire potrebbe aiutarti.
surui,

@surui, grazie, lo vedrò
sachin

Posso raccomandare di usare le promesse per cose asincrone e testarle, quindi è un gioco da ragazzi con Chai come promessa
Krym,

Risposte:


344

Puoi impostare il timeout durante l'esecuzione del test:

mocha --timeout 15000

Oppure puoi impostare il timeout per ciascuna suite o ciascun test a livello di codice:

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

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

Per maggiori informazioni consultare la documentazione .


3
la versione più corta è -t. se si utilizza mocha-test per eseguire mocha dall'attività grunt, questo è supportato anche nell'oggetto opzioni options:{timeout:15000}.
svassr,

5
Cordiali saluti: passare funzioni freccia a Mocha è scoraggiato. mochajs.org/#arrow-functions
c0ming

4
Le funzioni freccia non sono scoraggiate nel link sopra. Dice solo che devi solo sapere cosa fanno in modo da non sbagliare quando hai bisogno di accedere al contesto. Non ho mai bisogno del contesto, poiché fare affidamento sui timeout è fragile e tutti i miei test vengono eseguiti in pochi ms, ma riscontro lo stesso problema quando si utilizza sinon-test. Usa ancora lambdas il 99% delle volte.
oligofren,

26
TypeError: this.timeout is not a functionquando si utilizza"mocha": "^3.5.0"
Junior Mayhé l'

5
@adi sei sicuro di non utilizzare le funzioni freccia? Per quanto riguarda asincronizzazione / attesa, è nei documenti, quindi dovrebbe funzionare (ed è la stessa cosa che usare le promesse). Sembra un'altra domanda però.
Andreas Hultgren,

80

Trovo che la "soluzione" del solo aumentare i timeout oscuri ciò che sta realmente accadendo qui, che è neanche

  1. Il tuo codice e / o le chiamate di rete sono troppo lente (dovrebbe essere inferiore a 100 ms per una buona esperienza utente)
  2. Le asserzioni (test) falliscono e qualcosa sta inghiottendo gli errori prima che Mocha riesca ad agire su di essi.

Di solito incontri # 2 quando Mocha non riceve errori di asserzione da una richiamata. Ciò è causato da qualche altro codice che ingoia l'eccezione più in alto nello stack. Il modo giusto di gestirlo è correggere il codice e non ingoiare l'errore .

Quando il codice esterno ingoia i tuoi errori

Nel caso in cui sia una funzione di libreria che non è possibile modificare, è necessario rilevare l'errore di asserzione e trasmetterlo a Mocha. Puoi farlo racchiudendo il callback di asserzione in un blocco try / catch e passare eventuali eccezioni al gestore fatto.

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

Naturalmente questa piastra di cottura può essere estratta in alcune funzioni di utilità per rendere il test un po 'più piacevole alla vista:

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

Accelerare i test di rete

Oltre a ciò, ti suggerisco di prendere i consigli su come iniziare a utilizzare gli stub di test per le chiamate di rete per far passare i test senza dover fare affidamento su una rete funzionante. Usando Mocha, Chai e Sinon i test potrebbero assomigliare a questo

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

});

Vedi i nisedocumenti di Sinon per maggiori informazioni.


Ho una vasta serie di test e ho appena passato tutte le promesse nelle mie specifiche per assicurarmi che tutte chiamino done()alla fine della promessa e sto già prendendo in giro le chiamate di rete usando Angular $httpBackend, ma senza fortuna. Avvolgere ogni singola specifica con un try-catch non sembra molto pragmatico. Altri suggerimenti? Grazie!
Gustavo Matias,

@GustavoMatias In realtà non hai menzionato il tuo problema, hai appena affermato che questa non è una soluzione per qualsiasi problema. Per favore, elabora :-) I tuoi test non stanno fallendo abbastanza velocemente? A volte falliscono, ma vorresti sapere perché? Difficile indovinare cosa si intende ottenere.
Oligofren,

ciao @oligofren! quella non era davvero la migliore spiegazione. C'è una spiegazione più dettagliata del mio problema qui stackoverflow.com/questions/34510048/… grazie!
Gustavo Matias,

"In generale, il modo più pulito (ma il più brutto) di affrontare questo problema è racchiudere il codice con un tentativo / cattura e passare eventuali eccezioni al gestore fatto." No, questo non è affatto il modo più pulito. Non da un colpo lungo. Il modo più pulito è scrivere codice che non inghiotte eccezioni. Ogni volta che ho visto qualcuno lamentarsi che Mocha non stava rilevando un test fallito, era perché c'era qualcosa che ingoiava l'eccezione. Aggiunta di un try.... catch...lavori in tutto il bug nel codice sotto test invece di correzione di esso.
Louis,

@ Forse potresti avere ragione sui perché qui, ma non riesco a verificarlo di punto in bianco. comunque, le persone hanno un problema con Mocha che sembra non essere in grado di rilevare qualche errore, e questo è un modo per gestirlo. il tuo approccio dato presuppone che il codice che ingoia l'errore non sia una funzione di libreria o simile, nel qual caso non sarebbe così facile da risolvere.
oligofren,

7

Un po 'in ritardo, ma qualcuno può usarlo in futuro ... Puoi aumentare il timeout del test aggiornando gli script nel tuo package.json con quanto segue:

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

Esegui i test utilizzando il comando test


Ha funzionato per me! Grazie!
RayLoveless

5

Se si utilizzano le funzioni freccia:

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

1

Per me il problema era in realtà la funzione di descrizione, che quando fornita una funzione freccia, fa perdere il timeout alla moka e si comporta in modo non coerente. (Usando ES6)

poiché nessuna promessa è stata respinta, ho riscontrato questo errore continuamente per diversi test che non riuscivano all'interno del blocco di descrizione

quindi come appare quando non funziona correttamente:

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

e questo funziona usando la funzione anonima

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

Spero che aiuti qualcuno, la mia configurazione per quanto sopra: (nodejs: 8.4.0, npm: 5.3.0, moka: 3.3.0)


0

Il mio problema non stava restituendo la risposta, quindi era sospeso. Se si utilizza express, assicurarsi che res.send (data), res.json (data) o qualunque sia il metodo api che si desidera utilizzare sia eseguito per il percorso che si sta testando.


0

Assicurati di risolvere / rifiutare le promesse utilizzate nei casi di test, sia che si tratti di spie o stub, accertati che vengano risolte / rifiutate.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.