В тестировании mocha при вызове асинхронной функции как избежать ошибки тайм-аута: превышен тайм-аут 2000ms
в моем приложении узла я использую mocha для тестирования моего кода. При вызове многих асинхронных функций с помощью mocha я получаю ошибку тайм-аута (Error: timeout of 2000ms exceeded.). Как я могу это решить?
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();
        });
    });
});
4 ответов
вы можете либо установить тайм-аут при запуске теста:
mocha --timeout 15000
или вы можете установить тайм-аут для каждого набора или каждого теста программно:
describe('...', function(){
  this.timeout(15000);
  it('...', function(done){
    this.timeout(15000);
    setTimeout(done, 15000);
  });
});
для получения дополнительной информации см. docs.
Я нахожу ,что" решение " просто увеличения таймаутов скрывает то, что действительно происходит здесь, что либо
- ваш код и / или сетевые вызовы слишком медленные (должны быть суб 100 мс для хорошего пользовательского опыта)
- утверждения (тесты) терпят неудачу, и что-то проглатывает ошибки, прежде чем Мокко сможет действовать на них.
вы обычно сталкиваетесь с #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);
    }
}
ускорение сетевых тестов
кроме этого, я предлагаю вам взять совет по началу использования тестовых заглушек для сетевых вызовов, чтобы тесты проходили без необходимости полагаться на функционирующую сеть. Используя Мокко, чай и Синон, тесты могут выглядеть примерно так это
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;
    });
});
посмотреть Синон это nise docs для получения дополнительной информации.
для меня проблема была на самом деле описать функцию, который при условии функции стрелки, заставляет mocha пропустить тайм-аут, и ведут себя не последовательно. (Используя ES6)
поскольку никакое обещание не было отклонено, я получал эту ошибку все время для разных тестов, которые терпели неудачу внутри блока описания
Так вот как это выглядит, когда не работает должным образом:
describe('test', () => { 
 assert(...)
})
и это работает с использованием анонимной функции
describe('test', function() { 
 assert(...)
})
Надежда он помогает кому-то, моя конфигурация выше: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)
немного поздно, но кто-то может использовать это в будущем...Вы можете увеличить время ожидания теста, обновив сценарии в пакете.json со следующим:
"scripts": {
     "test": "test --timeout 10000" //Adjust to a value you need
  }
запустить тесты с помощью команды test
