Під час тестування на мокке під час виклику асинхронної функції, як уникнути тайм-ауту Помилка: перевищено час очікування 2000 мс


200

У своїй програмі для вузла я використовую 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();
        });

    });

});

це інтеграційний тест? часу для тестування багато часу - можливо, вам варто розглянути питання про заглушки - github.com/thlorenz/proxyquire може допомогти вам.
surui

@surui дякую, я буду дивитись на це
sachin

Я можу порекомендувати використовувати обіцянки для асинхронних речей та протестувати її тоді, як вітер із Чаєм, як обіцяють
Крим

Відповіді:


344

Ви можете встановити час очікування під час запуску тесту:

mocha --timeout 15000

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

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

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

Для отримання додаткової інформації дивіться документи .


3
скорочена версія є -t. якщо ви використовуєте mocha-test для запуску mocha з грунтового завдання, це також підтримується в об'єкті параметрів options:{timeout:15000}.
svassr

5
FYI: передача функцій стрілок на Mocha не перешкоджає. mochajs.org/#arrow-functions
c0ming

4
Функції стрілки не перешкоджають посиланням вище. Це просто говорить, що вам просто потрібно знати, що вони роблять, щоб ви не закручувались, коли потребували доступу до контексту. Мені ніколи не потрібен контекст, оскільки покладаючись на тайм-аути, є крихким, і всі мої тести виконуються за кілька мс, але я стикаюся з тією ж проблемою, коли використовую тест на синон. Ще вживають лямбда у 99% часу.
олігофрен

26
TypeError: this.timeout is not a functionпри використанні"mocha": "^3.5.0"
Junior Mayhé

5
@adi Ви впевнені, що не використовуєте функції стрілок? Що стосується асинхронізації / очікування, то в документах так і має працювати (і це те саме, що і для використання обіцянок). Хоча це звучить як інше питання.
Андреас Хультгрен

80

Я вважаю, що "рішення" просто збільшити тайм-аути затьмарює те, що відбувається насправді, що є

  1. Ваш код та / або мережеві дзвінки занадто повільні (для хорошої роботи з користувачем має бути менше 100 мс)
  2. Твердження (тести) провалюються, і щось проковтне помилки, перш ніж Моха зможе їх діяти.

Ви, як правило, стикаєтеся з №2, коли Mocha не отримує помилок твердження від зворотного дзвінка. Це викликано деяким іншим ковтанням коду, що виключає подальше стек. Правильний спосіб вирішити це - виправити код і не проковтнути помилку .

Коли зовнішній код проковтує ваші помилки

У випадку, якщо це функція бібліотеки, яку ви не можете змінити, вам потрібно зафіксувати помилку твердження і самостійно передати її на 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);
    }
}

Прискорення мережевих тестів

Крім цього, я пропоную вам підібрати поради щодо початку використання тестових заглушок для мережевих дзвінків, щоб тести проходили, не покладаючись на функціонуючу мережу. Використання Mocha, 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;
    });

});

Докладнішу інформацію див. У niseдокументах Сінона .


У мене величезний набір тестів, і я просто пройшов усі обіцянки в своїх специфікаціях, щоб переконатися, що всі вони дзвонять done()в кінці обіцянки, і я вже знущаюся над мережевими дзвінками за допомогою програми Angular $httpBackend, але не пощастило. Обертання кожної специфіки пробним уловом не здається дуже прагматичним. Будь-які інші пропозиції? Дякую!
Густаво Матіас

@GustavoMatias Ви насправді не згадали, у чому полягає ваша проблема, просто заявили, що це не є рішенням того, з чим у вас виникають проблеми. Будь ласка, уточнюйте :-) Невже ваші тести не проходять досить швидко? Вони часом не вдається, але ви хочете знати, чому? Важко здогадатися, чого ви маєте намір досягти.
олігофрен

привіт @oligofren! це було не найкращим поясненням. Тут є більш детальне пояснення моєї проблеми: stackoverflow.com/questions/34510048/… дякую!
Густаво Матіас

"Взагалі, найчистіший (але найгідніший) спосіб вирішити цю проблему - обернути свій код спробувати" catch "та передати будь-які винятки зробленому оброблювачу." Ні, це зовсім не найчистіший спосіб. Не довгим пострілом. Найчистіший спосіб - написати код, який не ковтає винятків. Кожен раз, коли я бачив, як хтось скаржився, що Моха не виявив невдалий тест, це було тому, що щось проковтнуло виняток. Додавання try.... catch...творів навколо помилки в тестований код, а не виправлення .
Луї

@Люди, можливо, ти маєш рацію щодо того, про що тут йдеться, але я не в змозі перевірити це начебто. у будь-якому випадку у людей є проблема, коли Моха, здається , не в змозі зрозуміти якусь помилку, і це спосіб її вирішення. Ваш даний підхід передбачає, що помилка ковтання коду - це не якась бібліотечна функція чи подібне, і в цьому випадку це було б не так легко вирішити.
олігофрен

7

Трохи пізно, але хтось може скористатись цим у майбутньому ... Ви можете збільшити час випробування, оновивши скрипти у своєму пакеті.json за допомогою наступного:

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

Запустіть свої тести за допомогою команди test


Працювали для мене! Дякую тобі!
RayLoveless

5

Якщо ви використовуєте функції стрілок:

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

1

Для мене проблема була фактично функцією опису, яка при наданні функції зі стрілкою призводить до того, що мокко пропускає тайм-аут, і веде себе не послідовно. (Використання ES6)

оскільки жодна обіцянка не була відхилена, я отримував цю помилку весь час для різних тестів, які не спрацьовували всередині блоку опису

так ось, як це виглядає, коли не працює належним чином:

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

і це працює за допомогою анонімної функції

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

Сподіваюся, це комусь допоможе, моя конфігурація для вищезазначеного: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)


0

У моєму питанні не було надсилання відповіді назад, тому воно зависло. Якщо ви використовуєте експрес, переконайтеся, що res.send (дані), res.json (дані) або будь-який метод api, який ви хочете використовувати, виконаний для маршруту, який ви тестуєте.


0

Не забудьте вирішити / відхилити обіцянки, використані в тестових випадках, будь то шпигуни чи заглушки, переконайтеся, що вони вирішують / відхиляють.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.