[javascript] NodeJS UnhandledPromiseRejectionWarning
그래서 이벤트 이미 터를 사용하는 구성 요소를 테스트하고 있습니다. 그렇게하기 위해 Mocha + Chai와 함께 Promises를 사용하는 솔루션을 생각해 냈습니다.
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();
});
});
콘솔에 ‘AssertionError : Promise error’메시지가 즉시 표시되므로 거부 함수가 호출되었지만 ‘UnhandledPromiseRejectionWarning’이 나타납니다.
(node : 25754) UnhandledPromiseRejectionWarning : 처리되지 않은 약속 거부 (거부 ID : 2) : AssertionError : 약속 오류 : 예상 {개체 (메시지, showDiff, …)}가 거짓 1 임) 올바른 이벤트로 전환해야 함
그리고 2 초 후
오류 : 시간 초과 2000ms를 초과했습니다. 이 테스트에서 done () 콜백이 호출되고 있는지 확인하십시오.
catch 콜백이 실행 된 이후로 더 이상합니다 (어떤 이유로 든 어설 션 실패로 인해 나머지 실행이 차단되었다고 생각합니다)
이제 재미있는 것은 assert.isNotOk(error...)
콘솔에서 경고없이 테스트가 정상적으로 실행 된다는 것 입니다. 캐치를 실행한다는 의미에서 여전히 ‘실패’합니다.
그러나 여전히, 나는 이러한 오류를 약속으로 이해할 수 없습니다. 누군가 나를 밝게 할 수 있습니까?
답변
이 문제는 다음으로 인해 발생합니다.
.catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
어설 션이 실패하면 오류가 발생합니다. 이 오류는 done()
코드가 오류를 일으켰 기 때문에 호출되지 않습니다. 이것이 시간 초과를 일으키는 원인입니다.
“처리되지 않은 약속 거부”가 아니라 오류가 던져 경우 때문에 실패 주장에 의해 발생 catch()
핸들러 및 후속가없는 catch()
핸들러 (에 설명 된대로 오류가 삼킨 얻을 것이다 이 문서 ). UnhandledPromiseRejectionWarning
이 사실을 경고 하는 경고입니다.
일반적으로 Mocha에서 약속 기반 코드를 테스트하려면 Mocha 자체가 이미 약속을 처리 할 수 있다는 사실에 의존해야합니다. 을 사용하지 done()
말고 대신 테스트에서 약속을 반환하십시오. 그런 다음 Mocha는 오류 자체를 포착합니다.
이처럼 :
it('should transition with the correct event', () => {
...
return new Promise((resolve, reject) => {
...
}).then((state) => {
assert(state.action === 'DONE', 'should change state');
})
.catch((error) => {
assert.isNotOk(error,'Promise error');
});
});
답변
sinon으로 스터 빙 할 때이 오류가 발생했습니다.
해결책은 스텁으로 약속을 해결하거나 거부 할 때 약속대로 npm 패키지를 사용 하는 것입니다.
대신에 …
sinon.stub(Database, 'connect').returns(Promise.reject( Error('oops') ))
사용하다 …
require('sinon-as-promised');
sinon.stub(Database, 'connect').rejects(Error('oops'));
resolves 메소드도 있습니다 (끝에 s를보십시오).
http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections를 참조 하십시오
답변
Mocha의 어설 션 라이브러리는 어설 션이 올바르지 않은 경우 오류를 발생시켜 작동합니다. 오류를 발생 시키면 catch
메소드에 제공된 실행기 함수에서 발생하더라도 약속이 거부됩니다 .
.catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
위의 코드에서 error
객체는 평가되어 true
어설 션 라이브러리에서 오류가 발생하지 않습니다. 오류의 결과로 done
메소드가 호출되지 않습니다. Mocha의 done
콜백은 이러한 오류를 허용하므로 Mocha의 모든 약속 체인을 간단히 종료 할 수 있습니다 .then(done,done)
. 이를 통해 done 메소드가 항상 호출되고 Mocha가 동기 코드에서 어설 션의 오류를 잡을 때와 같은 방식으로 오류가보고됩니다.
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');
})).then(done,done);
});
Mocha에서 약속을 테스트 할 때 .then (done, done)을 사용한다는 아이디어에 대해이 기사 를 신뢰합니다 .
답변
UnhandledPromiseRejectionWarning
테스트 환경 외부 에서 오류 / 경고를 찾는 사람들에게는 아마도 코드의 아무도 아무도 약속의 최종 오류를 처리하지 않기 때문일 수 있습니다.
예를 들어,이 코드는이 질문에보고 된 경고를 표시합니다.
new Promise((resolve, reject) => {
return reject('Error reason!');
});
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
.catch()
오류를 추가 하거나 처리하면 경고 / 오류가 해결됩니다.
new Promise((resolve, reject) => {
return reject('Error reason!');
}).catch(() => { /* do whatever you want here */ });
또는 then
함수 에서 두 번째 매개 변수 사용
new Promise((resolve, reject) => {
return reject('Error reason!');
}).then(null, () => { /* do whatever you want here */ });
답변
나는이 문제에 직면했다 :
(node : 1131004) UnhandledPromiseRejectionWarning : 처리되지 않은 약속 거부 (판정 ID : 1) : TypeError : res.json은 함수가 아닙니다 (노드 : 1131004) DeprecationWarning : 처리되지 않은 약속 거부는 더 이상 사용되지 않습니다. 앞으로 처리되지 않은 약속 거부는 0이 아닌 종료 코드로 Node.j 프로세스를 종료합니다.
실수였습니다. res
에서 객체를 바꾸고 then(function(res)
있었으므로 res
결과로 변경 되어 이제는 작동 중입니다.
잘못된
module.exports.update = function(req, res){
return Services.User.update(req.body)
.then(function(res){//issue was here, res overwrite
return res.json(res);
}, function(error){
return res.json({error:error.message});
}).catch(function () {
console.log("Promise Rejected");
});
보정
module.exports.update = function(req, res){
return Services.User.update(req.body)
.then(function(result){//res replaced with result
return res.json(result);
}, function(error){
return res.json({error:error.message});
}).catch(function () {
console.log("Promise Rejected");
});
서비스 코드 :
function update(data){
var id = new require('mongodb').ObjectID(data._id);
userData = {
name:data.name,
email:data.email,
phone: data.phone
};
return collection.findAndModify(
{_id:id}, // query
[['_id','asc']], // sort order
{$set: userData}, // replacement
{ "new": true }
).then(function(doc) {
if(!doc)
throw new Error('Record not updated.');
return doc.value;
});
}
module.exports = {
update:update
}
답변
E7 async / await에 대한 나의 경험은 다음과 같습니다 .
async helperFunction()
테스트에서 전화를 한 경우 … (ES7 async
키워드에 대한 설명이 하나 있습니다.)
→ 확인하십시오. await helperFunction(whateverParams)
(알다시피 자연스럽게, 일단 알면 …)
그리고 그것이 작동하려면 ( ‘기다리는 예약어’를 피하기 위해) 테스트 함수에 외부 비동기 마커가 있어야합니다.
it('my test', async () => { ...
답변
Chai-Webdriver for Selenium과 비슷한 경험을했습니다. await
어설 션에 추가 하고 문제를 해결했습니다.
Cucumberjs를 사용한 예 :
Then(/I see heading with the text of Tasks/, async function() {
await chai.expect('h1').dom.to.contain.text('Tasks');
});