2013-05-17 6 views
147

В моем приложении-узле я использую мокко для проверки кода. При вызове многих асинхронных функций с использованием mocha я получаю ошибку тайм-аута (Error: timeout of 2000ms exceeded.). Как я могу это решить?В мокко-тестировании при вызове асинхронной функции, как избежать таймаута Ошибка: превышение тайм-аута в 2000 мс

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

    }); 

}); 
+0

Это тест интеграции? для запуска теста достаточно времени - возможно, вам стоит подумать о заглушках - https://github.com/thlorenz/proxyquire может вам помочь. – surui

+0

@surui спасибо, я посмотрю на это – sachin

+0

Могу ли я порекомендовать использовать обещания для асинхронного материала и тестировать его, тогда это легкий ветерок с [Чей как обещание] (https://www.npmjs.com/package/chai-as-promised) – Krym

ответ

267

Вы можете установить тайм-аут при запуске теста:

mocha --timeout 15000 

Или вы можете установить тайм-аут для каждого набора или каждый тест программно:

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

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

Для получения дополнительной информации см docs.

+0

более короткая версия - '' '-t'''. если вы используете mocha-test для запуска mocha из задачи grunt, это также поддерживается в опциях object '' 'options: {timeout: 15000}' ''. – svassr

+0

Для 'it' вы должны передать' done' как 'setTimeout (сделано, 200);' в соответствии с [docs] (http://mochajs.org/#suite-specific-timeouts) –

+0

что делать, если вы 're используя co-wrap вокруг ваших тестов mocha, чтобы позволить функции генератора, тогда этот тайм-аут не работает – PositiveGuy

72

Я считаю, что «решение» просто увеличивая время ожидания затемняет то, что происходит на самом деле здесь, что либо

  1. Ваш код и/или сетевые вызовы являются слишком медленно (должно быть суб 100 мс хороший пользовательский опыт)
  2. Утверждения (тесты) терпят неудачу, и что-то поглощает ошибки, прежде чем Моча сможет действовать на них.

Обычно вы сталкиваетесь с №2, когда Mocha не получает ошибок утверждения из обратного вызова. Это вызвано тем, что другой код проглатывает исключение в стеке. Правильный способ справиться с этим - исправить код и не проглотить ошибку.

Когда внешний код проглатывает свои ошибки

В случае это функция библиотеки, что вы не можете изменить, вы должны поймать ошибку утверждение и передать его на Мокко самостоятельно. Вы делаете это, обертывая свой ответ на запрос в блоке try/catch и передавая все исключения обработчику.

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

Это шаблонный, конечно, может быть извлечена в некоторой функции полезности, чтобы сделать тест немного более приятным для глаз:

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

Ускорение сетевых тестов

Другие, чем Я предлагаю вам подобрать совет, чтобы начать использовать тестовые заглушки для сетевых вызовов, чтобы пройти тесты без необходимости полагаться на функционирующую сеть. Использование Мокко, Chai и Sinon на тестах может выглядеть примерно так

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

}); 

Смотрите Sinon's nise docs для получения дополнительной информации.

+0

У меня есть огромный набор тестов, и я просто выполнил все обещания в своих спецификациях, чтобы убедиться, что они все называют 'done()' в конце обещания, и я уже высмеиваю сетевые вызовы, используя Angular's ' $ httpBackend', но не повезло. Обертка каждой отдельной спецификации с помощью try-catch не кажется очень прагматичной. Любые другие предложения? благодаря! –

+0

@GustavoMatias. На самом деле вы не упомянули о своей проблеме, просто заявили, что это не решение того, с чем у вас возникают проблемы. Пожалуйста, тщательно продумайте :-) Являются ли ваши тесты не очень быстрыми? Иногда они терпят неудачу, но вы хотели бы знать, почему? Трудно догадаться, чего вы намереваетесь достичь. – oligofren

+0

привет @oligofren! это не было лучшим объяснением. Более подробное объяснение моей проблемы здесь http://stackoverflow.com/questions/34510048/angular-mocha-memory-leak?noredirect1_comment56767589_34510048 спасибо! –

-2

Для асинхронных вызовов мы должны использовать выполненный обратный вызов. Если вы передадите его в(), тогда назовите его также, то есть done(); в противном случае независимо от того, сколько времени вы увеличите, он будет продолжать отсчет времени. В противном случае не передавайте его. Если это не так, и в тестовом случае много обработки, то увеличение значения поможет.

+0

OP уже использует обратный вызов 'done'. Ваш ответ на самом деле не помогает решить проблему, которая была представлена ​​в вопросе. – Louis

1

Для меня проблема была на самом деле функцией описания, которая при условии, что функция стрелки, вызывает мокко пропустить тайм-аут и вести себя не последовательно. (Использование ES6)

, поскольку не обещает было отвергнут я все время получаю эту ошибку для различных тестов, которые были неудовлетворительными внутри описания блока

так это, как он выглядит, когда он не работает должным образом:

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

и это работает, используя анонимную функцию

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

Надеется, что это поможет кому-то, моей конфигурации выше: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)

+0

Как упоминалось в комментариях к другим ответам: https://mochajs.org/#arrow-functions – tkane2000