Podczas testowania mokki podczas wywoływania funkcji asynchronicznej, jak uniknąć przekroczenia limitu czasu Błąd: przekroczono limit 2000 ms

200

W mojej aplikacji węzłowej używam mokki do testowania mojego kodu. Podczas wywoływania wielu funkcji asynchronicznych za pomocą mocha, pojawia się błąd przekroczenia limitu czasu ( Error: timeout of 2000ms exceeded.). Jak mogę to rozwiązać?

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
źródło
czy to test integracyjny? uruchomienie testu to dużo czasu - może powinieneś rozważyć kody pośredniczące - github.com/thlorenz/proxyquire może ci pomóc.
surui
@surui dziękuję, popatrzę na to
sachin
Czy mogę polecić stosowanie obietnic do rzeczy asynchronicznych i testowanie ich, a wtedy Chai jest obietnicą
Krym

Odpowiedzi:

344

Możesz ustawić limit czasu podczas uruchamiania testu:

mocha --timeout 15000

Lub możesz ustawić limit czasu dla każdego pakietu lub każdego testu programowo:

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

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

Aby uzyskać więcej informacji, zobacz dokumenty .

Andreas Hultgren
źródło
3
krótsza wersja to -t. jeśli użyjesz testu mokki do uruchomienia mokki z zadania chrząknięcia, jest to również obsługiwane w obiekcie opcji options:{timeout:15000}.
svassr
5
FYI: odradza się przekazywanie funkcji strzałek Mocha. mochajs.org/#arrow-functions
c0ming
4
Funkcje strzałek nie są odradzane w powyższym linku. Mówi tylko, że musisz tylko wiedzieć, co oni robią, więc nie spieprzysz, gdy potrzebujesz dostępu do kontekstu. Nigdy nie potrzebuję kontekstu, ponieważ poleganie na limitach czasu jest kruche, a wszystkie moje testy uruchamiane są w ciągu kilku ms, ale napotykam ten sam problem podczas korzystania z testu sinon. Nadal używaj lambdów w 99% przypadków.
oligofren
26
TypeError: this.timeout is not a functionprzy użyciu"mocha": "^3.5.0"
Junior Mayhé,
5
@adi czy na pewno nie używasz funkcji strzałek? Jeśli chodzi o async / czekaj, to jest w dokumentach, więc powinno działać (i to samo, co przy użyciu obietnic). Brzmi jak kolejne pytanie.
Andreas Hultgren
80

Uważam, że „rozwiązanie” polegające na zwiększeniu limitów czasowych zaciemnia to, co naprawdę się tutaj dzieje, co też jest

  1. Twój kod i / lub połączenia sieciowe są zbyt wolne (powinny być mniejsze niż 100 ms, aby zapewnić dobrą obsługę)
  2. Twierdzenia (testy) zawodzą i coś połyka błędy, zanim Mocha będzie w stanie na nie zareagować.

Zazwyczaj napotykasz numer 2, gdy Mocha nie otrzymuje błędów potwierdzenia od oddzwonienia. Jest to spowodowane tym, że jakiś inny kod połyka wyjątek na górze stosu. Prawidłowym sposobem radzenia sobie z tym jest naprawienie kodu, a nie połknięcie błędu .

Gdy kod zewnętrzny połyka błędy

Jeśli jest to funkcja biblioteki, której nie możesz zmodyfikować, musisz złapać błąd asercji i sam przekazać go Mocha. Robisz to, zawijając swoje wywołanie zwrotne asercji w bloku try / catch i przekazując wszelkie wyjątki do gotowej procedury obsługi.

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

Tę płytę kotłową można oczywiście wyodrębnić do jakiejś funkcji użytkowej, aby uczynić test nieco bardziej przyjemnym dla oka:

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

Przyspieszenie testów sieciowych

Poza tym sugeruję, abyś zapoznał się z poradami na temat rozpoczynania używania kodów testowych do połączeń sieciowych w celu przeprowadzenia testów bez konieczności polegania na działającej sieci. W przypadku Mocha, Chai i Sinon testy mogą wyglądać mniej więcej tak

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

});

Zobacz dokumentację Sinona,nise aby uzyskać więcej informacji.

oligofren
źródło
Mam ogromny zestaw testów i po prostu przejrzałem wszystkie obietnice zawarte w moich specyfikacjach, aby upewnić się, że wszystkie dzwonią done()pod koniec obietnicy i już wyśmiewam połączenia sieciowe za pomocą Angulara $httpBackend, ale nie mam szczęścia. Zawinięcie każdej specyfikacji w try-catch nie wydaje się bardzo pragmatyczne. Jakieś inne sugestie? dzięki!
Gustavo Matias,
@GustavoMatias Tak naprawdę nie wspomniałeś o swoim problemie, po prostu stwierdziłeś, że nie jest to rozwiązanie tego, z czym masz problemy. Proszę rozwinąć :-) Czy twoje testy nie kończą się wystarczająco szybko? Czasami zawodzą, ale chciałbyś wiedzieć, dlaczego? Trudno zgadnąć, co zamierzasz osiągnąć.
oligofren
cześć @oligofren! to nie było najlepsze wytłumaczenie. Bardziej szczegółowe wyjaśnienie mojego problemu znajduje się tutaj stackoverflow.com/questions/34510048/... dzięki!
Gustavo Matias
„Ogólnie najczystszym (ale najbrzydszym) sposobem radzenia sobie z tym problemem jest owijanie kodu metodą try / catch i przekazywanie wyjątków do gotowej procedury obsługi.” Nie, to wcale nie jest najczystszy sposób. Nie z dystansu. Najczystszym sposobem jest napisanie kodu, który nie połyka wyjątków. Za każdym razem, gdy widziałem, jak ktoś narzeka, że ​​Mocha nie wykrywa nieudanego testu, to dlatego, że coś przełykało wyjątek. Dodanie try.... catch...działa wokół błędu w testowanym kodzie, zamiast go naprawić .
Louis,
@Louis, być może masz rację co do tego, dlaczego tu jesteś, ale nie jestem w stanie zweryfikować tego nieoczekiwanie. w każdym razie ludzie mają problem z Mocha, która najwyraźniej nie jest w stanie złapać jakiegoś błędu, i jest to sposób na poradzenie sobie z tym. twoje podejście zakłada, że ​​kod połykający błąd nie jest jakąś funkcją biblioteczną lub podobną, w którym to przypadku nie można go tak łatwo rozwiązać.
oligofren,
7

Trochę późno, ale ktoś może to wykorzystać w przyszłości ... Możesz zwiększyć limit czasu testu, aktualizując skrypty w pliku package.json, wykonując następujące czynności:

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

Uruchom testy za pomocą polecenia test

Daniel Mbeyah
źródło
Pracował dla mnie! Dzięki Ci!
RayLoveless
5

Jeśli używasz funkcji strzałek:

it('should do something', async () => {
  // do your testing
}).timeout(15000)
lukas_o
źródło
1

Dla mnie problemem była właściwie funkcja opisu, która po udostępnieniu funkcji strzałki powoduje, że mokka nie może przekroczyć limitu czasu i nie zachowuje się konsekwentnie. (Korzystanie z ES6)

ponieważ żadna obietnica nie została odrzucona, cały czas otrzymywałem ten błąd dla różnych testów, które zawiodły w bloku opisu

tak to wygląda, gdy nie działa poprawnie:

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

i to działa przy użyciu funkcji anonimowej

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

Mam nadzieję, że to komuś pomoże, moja konfiguracja dla powyższego: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)

syberkitten
źródło
0

Moim problemem nie było odesłanie odpowiedzi, więc zawiesiło się. Jeśli używasz ekspresowego, upewnij się, że res.send (dane), res.json (dane) lub jakakolwiek metoda interfejsu API, której chcesz użyć, jest wykonywana dla testowanej trasy.

il0v3d0g
źródło
0

Upewnij się, że rozwiązałeś / odrzuciłeś obietnice zastosowane w przypadkach testowych, czy to szpiedzy, czy pośrednicy, upewnij się, że rozwiązują / odrzucają.

kavigun
źródło