Итак, я тестирую компонент, который полагается на эмиттер событий. Для этого я придумал решение, использующее Promises с Mocha + Chai:
it('should transition with the correct event', (done) => {
const cFSM = new CharacterFSM({}, emitter, transitions);
let timeout = null;
let resolved = false;
new Promise((resolve, reject) => {
emitter.once('action', resolve);
emitter.emit('done', {});
timeout = setTimeout(() => {
if (!resolved) {
reject('Timedout!');
}
clearTimeout(timeout);
}, 100);
}).then((state) => {
resolved = true;
assert(state.action === 'DONE', 'should change state');
done();
}).catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
});
На консоли я получаю сообщение «UnhandledPromiseRejectionWarning», хотя вызывается функция отклонения, поскольку сразу отображается сообщение «AssertionError: ошибка обещания».
(узел: 25754) UnhandledPromiseRejectionWarning: необработанное отклонение обещания (идентификатор отклонения: 2): AssertionError: ошибка обещания: ожидается, что {Object (message, showDiff, ...)} будет ложным 1) должен перейти с правильным событием
А потом, через 2 секунды, я получаю
Ошибка: превышено время ожидания 2000 мс. Убедитесь, что в этом тесте вызывается обратный вызов done ().
Что еще более странно, поскольку был выполнен обратный вызов catch (я думаю, что по какой-то причине ошибка assert помешала остальной части выполнения)
А теперь самое забавное: если я закомментирую assert.isNotOk(error...)
тест, он будет работать нормально, без предупреждения в консоли. Он по-прежнему «терпит неудачу» в том смысле, что выполняет захват.
Но все же я не могу понять эти ошибки с обещанием. Может кто меня просветить?
Ответы:
Проблема вызвана следующим:
Если утверждение терпит неудачу, оно выдаст ошибку. Эта ошибка приведет к тому, что
done()
никогда не будет вызвана, потому что код был ошибочным до нее. Вот что вызывает тайм-аут.«Неизвестное отказ обещания» также вызвано неудавшимся утверждением, потому что если ошибка возникают в
catch()
обработчике, и не существует последующийcatch()
обработчик , ошибка будет получить проглатывание (как описано в этой статье ).UnhandledPromiseRejectionWarning
Предупреждение предупреждает вас этот факт.В общем, если вы хотите протестировать код на основе обещаний в Mocha, вы должны полагаться на тот факт, что сам Mocha уже может обрабатывать обещания. Вы не должны использовать
done()
, а вместо этого верните обещание из своего теста. Тогда Mocha сам поймает любые ошибки.Как это:
источник
catch
обработчик, вероятно, должен быть передан в качестве второго аргументаthen
. Однако я не совсем уверен, в чем заключалась цель OP, поэтому я оставил все как есть.done.fail('msg')
в этом случае.Получил эту ошибку при заглушке с синоном.
Исправление состоит в том, чтобы использовать npm-пакет sinon-as-обещанный при разрешении или отклонении обещаний с заглушками.
Вместо того ...
Используйте ...
Также существует метод resolves (обратите внимание на s в конце).
См. Http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejection
источник
Библиотеки утверждений в Mocha работают, выкидывая ошибку, если утверждение было неверным. Выдача ошибки приводит к отклонению обещания, даже если оно выбрано функцией исполнителя, предоставленной
catch
методу.В приведенном выше коде
error
объект оцениваетсяtrue
так, что библиотека утверждений выдает ошибку ... которая никогда не перехватывается. В результате ошибкиdone
метод никогда не вызывается.done
Обратный вызов Mocha принимает эти ошибки, поэтому вы можете просто завершить все цепочки обещаний в Mocha с помощью.then(done,done)
. Это гарантирует, что метод done всегда вызывается, и об ошибке будет сообщаться так же, как когда Mocha перехватывает ошибку утверждения в синхронном коде.Я отдаю должное этой статье за идею использования .then (done, done) при тестировании обещаний в Mocha.
источник
Для тех, кто ищет ошибку / предупреждение
UnhandledPromiseRejectionWarning
за пределами тестовой среды, возможно, это связано с тем, что никто в коде не заботится о возможной ошибке в обещании:Например, этот код покажет предупреждение, указанное в этом вопросе:
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
и добавление
.catch()
или обработка ошибки должно устранить предупреждение / ошибкуИли используя второй параметр в
then
функцииисточник
new Promise((resolve, reject) => { return reject('Error reason!'); })
а в функции,function test() { return new Promise((resolve, reject) => { return reject('Error reason!'); });}
поэтому внутри функции нам не нужно использовать,.catch()
но для успешной обработки ошибок ее достаточно использовать при вызове этой функцииtest().catch(e => console.log(e))
или версии async / awaittry { await test() } catch (e) { console.log(e) }
Я столкнулся с этой проблемой:
Это была моя ошибка, я заменял
res
объект вthen(function(res)
, поэтому изменилres
на результат, и теперь он работает.Неправильно
коррекция
Сервисный код:
источник
Вот мой опыт работы с E7 async / await :
Если у вас есть
async helperFunction()
звонок из вашего теста ... (async
я имею в виду одно явно с ключевым словом ES7 )→ убедитесь, что вы называете это так
await helperFunction(whateverParams)
(ну да, естественно, как только вы узнаете ...)И для того, чтобы это сработало (чтобы избежать «ожидание - это зарезервированное слово»), ваша тестовая функция должна иметь внешний маркер async:
источник
await helperFunction(...)
.async
Функция возвращает обещание. Вы можете просто обработать возвращенное обещание, как если бы вы поступили с не отмеченной функцией,async
которая возвращает обещание. Дело в том, чтобы выполнить обещание, и точка. Есть функцияasync
или нет, не имеет значения.await
это всего лишь один из множества способов выполнить обещание.UnhandledPromiseRejectionWarning
я забыл об ожидании ... таким образом, этот ответ.У меня был аналогичный опыт с Chai-Webdriver для Selenium. Я добавил
await
к утверждению, и оно устранило проблему:Пример использования Cucumberjs:
источник
Я решил эту проблему после удаления веб-пакета (проблема с реакцией js).
источник