2015-01-27 4 views
6

Я строю модуль узла и стараюсь изо всех сил пытаться выполнить тестирование. Я установил mocha и chai для обработки теста. У меня возникла проблема с тестированием моих асинхронных методов (методов, возвращающих обещания).Assert Is Breaking Async Function in Mocha Test

В следующем тесте я тестирую метод объекта «Обновление».

it('Should return a list of versions for the default git repo', function (done) { 
    fs.writeFileSync(appSetup.CONFIG_FILENAME, JSON.stringify(appSetup.DEFAULT_CONFIG)); 

    var upgrade = new Upgrade({ 
     quiet: true 
    }); 

    upgrade.getVersions().then(function (versions) { 
     assert(versions && versions.length > 0, 'Should have at least one version.'); 
     assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
     done(); 
    }, done); 
    }); 

getVersions() вызов возвращает обещание как метод асинхронной. Когда обещание решает, я хочу проверить значение, возвращаемое в переменной versions.

assert(versions && versions.length > 0, 'Should have at least one version.'); - это фактическое испытание. Я добавил assert.equal(1, 2);, потому что заметил, что когда тест должен завершиться неудачно, тестовый пример даже не появится в тестовом списке.

Я предполагаю, что вызов assert бросает исключение, которое Mocha должно забрать. Однако он попадает в ловушку в обетованиях функции then.

Что здесь происходит? Почему, когда утверждение будет терпеть неудачу в этом методе, не отображает ли тестовый пример в списке (он не отображается как сбой, как будто он не существует)?

ответ

11

Суть вопроса в том, что код у вас есть, по существу:

try { 
    var versions = upgrade.getVersions(); 
} catch (err){ 
    return done(err); 
} 

assert(versions && versions.length > 0, 'Should have at least one version.'); 
assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
done(); 

Глядя на это, должно быть ясно, что если утверждения throw, то ни callback будет работать.

try { 
    var versions = upgrade.getVersions(); 
    assert(versions && versions.length > 0, 'Should have at least one version.'); 
    assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
    done(); 
} catch (err){ 
    return done(err); 
} 

больше походит на то, что вы хотите, что бы:

upgrade.getVersions().then(function (versions) { 
    assert(versions && versions.length > 0, 'Should have at least one version.'); 
    assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
}).then(done, done); 

Узел, что это будет выполняться утверждения, а затем переместить обратные вызовы во вторичный .then(), что всегда будет обрабатывать ошибки.

Тем не менее, было бы гораздо легче просто вернуть обещание в

return upgrade.getVersions().then(function (versions) { 
    assert(versions && versions.length > 0, 'Should have at least one version.'); 
    assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
}); 

позволить Мокко сам контролировать обещание без обратного вызова.

+0

Я не уверен, что понимаю, почему этот ответ работает. Исходный код в основном: async(). Then (function() { throw new Error(); // если эта строка выбрасывается, то это переходит к обработчику .catch() done(); }) ,catch (done) // register done() как обработчик ошибок. Если бросок происходит, вызов 'done()' в обработчике 'then()' не выполняется, но вместо этого вызывается обработчик '.catch()' ... который все еще 'done'. –

+0

Упс, комментарии не позволяют блокировать блоки и блокируются через 5 минут. Извините за форматирование дерьма :( –

+0

'.then (fn, done)' не эквивалентен '.then (fn) .catch (done);', это ядро ​​разницы. В первом случае, если 'fn' throws , это необработанная ошибка, во втором примере вызывается 'done'. – loganfsmyth

4

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

Тест будет отображаться в, если вы дадите ему значение тайм-аута, которое вы, вероятно, должны сделать.

Все, что сказал, mocha понимает обещания. Вам не нужно иметь дело с обратными вызовами на всех:

it('Should return a list of versions for the default git repo', function() { 
    fs.writeFileSync(appSetup.CONFIG_FILENAME, JSON.stringify(appSetup.DEFAULT_CONFIG)); 

    var upgrade = new Upgrade({ 
     quiet: true 
    }); 

    return upgrade.getVersions().then(function (versions) { 
     assert(versions && versions.length > 0, 'Should have at least one version.'); 
     assert.equal(1, 2); 
    }); 
    }); 
+0

Хотелось бы, чтобы я принял ваши ответы! –