Как правильно проверить обещания с мокко и чай?
следующий тест ведет себя странно:
it('Should return the exchange rates for btc_ltc', function(done) {
var pair = 'btc_ltc';
shapeshift.getRate(pair)
.then(function(data){
expect(data.pair).to.equal(pair);
expect(data.rate).to.have.length(400);
done();
})
.catch(function(err){
//this should really be `.catch` for a failed request, but
//instead it looks like chai is picking this up when a test fails
done(err);
})
});
как я должен правильно обрабатывать отклоненное обещание (и проверить его)?
как я должен правильно обрабатывать неудачный тест (т. е.:expect(data.rate).to.have.length(400);
?
вот реализация, которую я тестирую:
var requestp = require('request-promise');
var shapeshift = module.exports = {};
var url = 'http://shapeshift.io';
shapeshift.getRate = function(pair){
return requestp({
url: url + '/rate/' + pair,
json: true
});
};
3 ответа:
проще всего было бы использовать встроенную поддержку обещаний Mocha в последних версиях:
it('Should return the exchange rates for btc_ltc', function() { // no done var pair = 'btc_ltc'; // note the return return shapeshift.getRate(pair).then(function(data){ expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); });// no catch, it'll figure it out since the promise is rejected });
или с современным узлом и асинхронным / await:
it('Should return the exchange rates for btc_ltc', async () => { // no done const pair = 'btc_ltc'; const data = await shapeshift.getRate(pair); expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); });
поскольку этот подход обещает конец в конец, его легче проверить, и вам не придется думать о странных случаях, о которых вы думаете, как о нечетных
done()
звонки везде.это преимущество Мокко имеет над другими библиотеками, как Жасмин на данный момент. Вы также можете чтобы проверить Чай, Как И Обещал что сделало бы его еще проще (нет
.then
), но лично я предпочитаю ясность и простоту текущая версия
как уже указал здесь, более новые версии Мокко уже обещают-осведомлены. Но так как ОП спросил конкретно о чае, то справедливо указать на
chai-as-promised
пакет, который обеспечивает чистый синтаксис для тестирования обещаний:используя chai-as-promised
вот как вы можете использовать chai-as-promised для тестирования обоих
resolve
иreject
случаи для обещания:var chai = require('chai'); var expect = chai.expect; var chaiAsPromised = require("chai-as-promised"); chai.use(chaiAsPromised); ... it('resolves as promised', function() { return expect(Promise.resolve('woof')).to.eventually.equal('woof'); }); it('rejects as promised', function() { return expect(Promise.reject('caw')).to.be.rejectedWith('caw'); });
без чай-как-пообещал
сделать это действительно ясно, что тестируется, вот тот же пример, закодированный без chai-as-promised:
it('resolves as promised', function() { return Promise.resolve("woof") .then(function(m) { expect(m).to.equal('woof'); }) .catch(function(m) { throw new Error('was not supposed to fail'); }) ; }); it('rejects as promised', function() { return Promise.reject("caw") .then(function(m) { throw new Error('was not supposed to succeed'); }) .catch(function(m) { expect(m).to.equal('caw'); }) ; });
вот мое мнение:
- используя
async/await
- не нужны дополнительные модули chai
- избегая проблемы с уловом, @TheCrazyProgrammer указал выше
функция отложенного обещания, которая не выполняется, если задана задержка 0:
const timeoutPromise = (time) => { return new Promise((resolve, reject) => { if (time === 0) reject({ 'message': 'invalid time 0' }) setTimeout(() => resolve('done', time)) }) } // ↓ ↓ ↓ it('promise selftest', async () => { // positive test let r = await timeoutPromise(500) assert.equal(r, 'done') // negative test try { await timeoutPromise(0) // a failing assert here is a bad idea, since it would lead into the catch clause… } catch (err) { // optional, check for specific error (or error.type, error. message to contain …) assert.deepEqual(err, { 'message': 'invalid time 0' }) return // this is important } assert.isOk(false, 'timeOut must throw') log('last') })
положительный тест достаточно прост. Неожиданный сбой (имитация по
500→0
) провалит тест автоматически, как отклоненное обещание обостряется.отрицательный тест использует try-catch-idea. Однако: "жалоба" на нежелательный проход происходит только после предложения catch (таким образом, он не попадает в предложение catch (), вызывая дальнейшие, но вводящие в заблуждение ошибки.
чтобы эта стратегия работала, необходимо вернуть тест из предложения catch. Если вы не хотите тестировать что-либо еще, используйте другой it () - блок.