そこで、イベント エミッターに依存するコンポーネントをテストしています。そのために、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」が表示されます。
(ノード:25754) UnhandledPromiseRejectionWarning: 処理されていないプロミス拒否 (拒否 ID: 2): AssertionError: プロミス エラー: { Object (message, showDiff, ...) } が偽であることが予想されます
- 正しいイベントで遷移するべきである
そして2秒後に
エラー: 2000 ミリ秒のタイムアウトを超えました。このテストで done() コールバックが呼び出されていることを確認してください。
キャッチコールバックが実行されたので、これはさらに奇妙です(何らかの理由でアサートの失敗により残りの実行が妨げられたと思います)
面白いことに、コメントアウトすると、assert.isNotOk(error...)
コンソールに警告が表示されずにテストが正常に実行されます。catch を実行するという意味では、まだ「失敗」しています。
しかし、Promise のこれらのエラーは理解できません。誰か教えてくれませんか?
ベストアンサー1
この問題の原因は次のとおりです:
.catch((error) => {
assert.isNotOk(error,'Promise error');
done();
});
アサーションが失敗すると、エラーがスローされます。このエラーによりdone()
、その前にコードがエラーになったため、呼び出されなくなります。これがタイムアウトの原因です。
の「未処理の約束の拒否」失敗したアサーションによっても発生します。ハンドラでエラーがスローされるとcatch()
、catch()
後続のハンドラがない、エラーは吸収されます(この記事)。このUnhandledPromiseRejectionWarning
警告はこの事実を警告しています。
一般的に、Mocha で Promise ベースのコードをテストする場合は、Mocha 自体がすでに Promise を処理できるという事実に頼る必要があります。 を使用するのではなくdone()
、代わりにテストから Promise を返す必要があります。そうすれば、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');
});
});