1. ホーム
  2. Web プログラミング
  3. ジャバスクリプト

[解決済み] テスト

2021-12-28 22:25:35

質問

最近、私は Mocha+Chai フレームワークを使用して、event-emitter に依存するコンポーネントをテストしています。 Promise を、次のようなコードで記述します。

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: Promise error

(node:25754) UnhandledPromiseRejectionWarning。Unhandled Promise Rejection (rejection id: 2)です。AssertionError: Promise error: expect { Object (message, showDiff, ...) } to be falsy

  1. は正しいイベントで遷移する必要があります。

そして、2秒後に

エラー: タイムアウト2000msを超えました。このテストでは、done()コールバックが呼び出されていることを確認してください。

キャッチコールバックが実行されたので、さらに奇妙なことになりました。

をコメントアウトすると assert.isNotOk(error...) を実行すると、コンソールに警告が表示されることなく、テストは正常に実行されます。しかし、catchを実行するという意味では、まだ「失敗」しています。

解決方法は?

この問題が発生する原因はこれです。

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

アサーションに失敗した場合は、エラーをスローします。このエラーは done() なぜなら、その前にコードがエラーになったからです。これがタイムアウトの原因です。

その "Unhandled promise rejection" はアサーションに失敗したことも原因です。 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');
  });
});