No teste mocha ao chamar a função assíncrona, como evitar o tempo limite Erro: o tempo limite de 2000ms foi excedido

200

No meu aplicativo de nó, estou usando o mocha para testar meu código. Ao chamar muitas funções assíncronas usando mocha, estou recebendo erro de tempo limite ( Error: timeout of 2000ms exceeded.). Como posso resolver isto?

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
fonte
é um teste de integração? leva muito tempo para a execução de um teste - talvez você deva considerar stubs - github.com/thlorenz/proxyquire pode ajudá-lo.
surui 17/05
@surui obrigado i olhará em que
sachin
Posso recomendamos o uso de promessas para o material assíncrono e testá-lo, em seguida, é uma brisa com Chai como promessa
Krym

Respostas:

344

Você pode definir o tempo limite ao executar seu teste:

mocha --timeout 15000

Ou você pode definir o tempo limite para cada suíte ou cada teste programaticamente:

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

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

Para mais informações, consulte os documentos .

Andreas Hultgren
fonte
3
versão mais curta é -t. se você usar o mocha-test para executar o mocha a partir da tarefa grunt, isso também será suportado no objeto options options:{timeout:15000}.
svassr
5
Para sua informação: passar as funções de flecha para Mocha é desencorajado. mochajs.org/#arrow-functions
c0ming
4
As funções de seta não são desencorajadas no link acima. Apenas diz que você só precisa saber o que eles fazem para não estragar tudo quando precisar acessar o contexto. Eu nunca preciso do contexto, pois confiar em intervalos é frágil, e todos os meus testes são executados em poucos ms, mas me deparo com o mesmo problema ao usar o sinon-test. Ainda use lambdas 99% do tempo.
precisa
26
TypeError: this.timeout is not a functionao usar"mocha": "^3.5.0"
Junior Mayhé
5
@ Você tem certeza de que não está usando as funções de seta? Com relação ao async / waitit, ele está nos documentos, portanto deve funcionar (e é o mesmo que usar promessas). Parece outra pergunta, no entanto.
Andreas Hultgren
80

Acho que a "solução" de apenas aumentar o tempo limite obscurece o que realmente está acontecendo aqui, que é

  1. Seu código e / ou chamadas de rede são muito lentas (deve ser inferior a 100 ms para uma boa experiência do usuário)
  2. As afirmações (testes) estão falhando e algo está engolindo os erros antes que o Mocha possa agir sobre eles.

Você geralmente encontra o número 2 quando o Mocha não recebe erros de asserção de um retorno de chamada. Isso é causado por outro código que engole a exceção ainda mais na pilha. A maneira correta de lidar com isso é corrigir o código e não engolir o erro .

Quando o código externo engole seus erros

Caso seja uma função de biblioteca que você não possa modificar, você precisará capturar o erro de asserção e passá-lo para o Mocha. Você faz isso agrupando seu retorno de chamada de asserção em um bloco try / catch e passa quaisquer exceções para o manipulador concluído.

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

É claro que este boilerplate pode ser extraído em alguma função de utilidade para tornar o teste um pouco mais agradável aos olhos:

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

Acelerando testes de rede

Além disso, sugiro que você siga o conselho de começar a usar stubs de teste para chamadas de rede para fazer com que os testes sejam aprovados sem precisar depender de uma rede que funcione. Usando Mocha, Chai e Sinon, os testes podem ser algo como isto

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

});

Veja os nisedocumentos de Sinon para mais informações.

oligofren
fonte
Eu tenho um grande conjunto de testes e apenas cumpri todas as promessas em minhas especificações para garantir que todos estejam ligando done()no final da promessa e já estou zombando das chamadas de rede usando o Angular $httpBackend, mas sem sorte. O agrupamento de todas as especificações com um try-catch não parece muito pragmático. Alguma outra sugestão? obrigado!
Gustavo Matias
@GustavoMatias Você realmente não mencionou qual é o seu problema, apenas afirmou que esta não é uma solução para o que você está tendo problemas. Elabore :-) Seus testes não estão falhando rápido o suficiente? Eles estão falhando às vezes, mas você gostaria de saber por quê? Difícil adivinhar o que você pretende alcançar.
precisa saber é
oi @oligofren! essa não era a melhor explicação de fato. Há uma explicação mais detalhada do meu problema aqui stackoverflow.com/questions/34510048/… obrigado!
Gustavo Matias
"Em geral, a maneira mais limpa (mas mais feia) de lidar com esse problema é agrupar seu código com uma tentativa / captura e passar quaisquer exceções para o manipulador pronto". Não, essa não é a maneira mais limpa. Não por um tiro longo. A maneira mais limpa é escrever um código que não engula exceções. Toda vez que eu vi alguém reclamar que Mocha não estava detectando um teste que falhou, foi porque havia algo engolindo a exceção. Adicionando try.... catch...obras ao redor do bug no código em teste em vez de correção -lo.
Louis
@ Louis, você pode estar certo sobre os porquês aqui, mas não consigo verificar do nada. de qualquer maneira, as pessoas têm um problema com o Mocha aparentemente incapaz de detectar algum erro, e essa é uma maneira de lidar com isso. sua abordagem especificada assume que o código que engole o erro não é uma função da biblioteca ou semelhante; nesse caso, não seria tão facilmente resolvido.
oligofren
7

Um pouco atrasado, mas alguém pode usar isso no futuro ... Você pode aumentar o tempo limite do teste atualizando scripts no seu package.json com o seguinte:

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

Execute seus testes usando o comando test

Daniel Mbeyah
fonte
Trabalhou para mim! Te agradece!
RayLoveless
5

Se você estiver usando funções de seta:

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

Para mim, o problema era, na verdade, a função de descrição, que, quando fornecida uma função de seta, faz com que o mocha perca o tempo limite e não se comporte de maneira consistente. (Usando o ES6)

como nenhuma promessa foi rejeitada, eu recebia esse erro o tempo todo para diferentes testes que estavam falhando dentro do bloco de descrição

então é assim que parece quando não está funcionando corretamente:

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

e isso funciona usando a função anônima

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

Espero que ajude alguém, minha configuração para o acima: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)

syberkitten
fonte
0

Meu problema não foi enviar a resposta de volta, por isso estava travando. Se você estiver usando express, certifique-se de que res.send (data), res.json (data) ou qualquer que seja o método api que você deseja usar seja executado para a rota que você está testando.

il0v3d0g
fonte
0

Certifique-se de resolver / rejeitar as promessas usadas nos casos de teste, sejam espiões ou stubs, certifique-se de que resolvam / rejeitam.

kavigun
fonte