だから、私はイベントエミッタに依存しているコンポーネントをテストしています。そのために、Promise with 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();
});
});
});
拒否機能が即座に 'AssertionError:Promise error'というメッセージを表示するので、コンソールでは 'UnhandledPromiseRejectionWarning'を受け取ります。
(node:25754)UnhandledPromiseRejectionWarning:未処理のpromise rejection(拒否ID:2):AssertionError:Promiseエラー:{Object(message、showDiff、...)}は偽造されているはずです1)正しいイベントに遷移する
そして、2秒後に
エラー:2000msのタイムアウトを超えました。このテストでdone()コールバックが呼び出されていることを確認してください。
Catchコールバックが実行されてからずっと奇妙です(何らかの理由でassertの失敗が残りの実行を妨げたと思います)
面白いことに、assert.isNotOk(error...)
をコメントアウトすると、テストはコンソールに何の警告もなく正常に実行されます。それは、それが捕獲を実行するという意味で、まだ「失敗」します。
しかしそれでも、私はこれらの間違いを約束して理解することはできません。誰かが私を悟らせることができますか?
問題はこれによって引き起こされます:
.catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
アサーションが失敗すると、エラーが発生します。このエラーにより、done()
が呼び出されることはなくなります。コードがエラーになる前にエラーが発生したためです。それがタイムアウトの原因です。
"Unhandled promise rejection" もアサーションの失敗によるものです。エラーがcatch()
ハンドラでスローされた場合、 で、その後にcatch()
ハンドラ がない場合、エラーは飲み込まれる( この記事 で説明されているように)。 UnhandledPromiseRejectionWarning
警告はこの事実を警告しています。
一般的に、Mochaでpromiseベースのコードをテストしたい場合は、Mocha自体が既にPromiseを処理できるという事実に頼るべきです。 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-as-promised を使うことです。
の代わりに ...
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-rejection を参照してください。
Mochaのアサーションライブラリは、アサーションが正しくなかった場合にエラーをスローすることで機能します。エラーをスローすると、catch
メソッドに提供されたexecutor関数でスローされた場合でも、拒否された約束が発生します。
.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
関数の2番目のパラメータを使う
new Promise((resolve, reject) => {
return reject('Error reason!');
}).then(null, () => { /* do whatever you want here */ });
テストからasync helperFunction()
が呼び出された場合は...(ES7のasync
キーワードを使用した1つの解説)
→確かに、あなたはそれをawait helperFunction(whateverParams)
と呼びます。
そしてそれが機能するためには(「待つことは予約語」を避けるため)、あなたのテスト関数は外側の非同期マーカーを持っていなければなりません:
it('my test', async () => { ...
私はこの問題に直面しました:
(node:1131004)UnhandledPromiseRejectionWarning:未処理のpromise rejection(拒否ID:1):TypeError:res.jsonは関数ではありません(node:1131004)DeprecationWarning:未処理のpromise rejectionは非推奨です。将来的には、処理されない約束拒否は、Node.jsのプロセスを0以外の終了コードで終了させるでしょう。
それは私の過ちでした。私はthen(function(res)
内の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
}
Webpackをアンインストールした後、この問題を解決しました(react js problem)。
Sudo uninstall webpack