1. ホーム
  2. reactjs

[解決済み] Jestにアサーションを期待する前に、すべての非同期コードの実行終了を待たせる方法

2023-01-20 17:32:50

質問

私はReactアプリケーションの統合テスト、すなわち、多くのコンポーネントを一緒にテストするテストを書いています。

問題は、非同期コールバックが実行される前にテストが実行されるようで、私のテストが失敗することです。

これを回避する方法はありますか?私はどうにかして非同期コードが終了するのを待つことができますか?

以下は、いくつかの悪い 疑似 のコードで、私の主張を説明します。

親コンポーネントをマウントすると、子コンポーネントが外部サービスから戻ってきたコンテンツをレンダリングすることをテストしたいと思いますが、これはモックにします。

class Parent extends component
{
     render ()
     {
         <div>
            <Child />
         </div>
     }
}
class Child extends component
{
     DoStuff()
     {
         aThingThatReturnsAPromise().then((result) => {
           Store.Result = result
         })
     }

    render()
    {
       DoStuff()
       return(<div>{Store.Result}</div>)


    }
}
function aThingThatReturnsAPromise()
{
     return new Promise(resolve =>{
          eternalService.doSomething(function callback(result) {
               resolve(result)
          }
    }

}

これをテストで実行すると、コールバックが起動される前にItが実行されてしまうので失敗します。

jest.mock('eternalService', () => {
    return jest.fn(() => {
        return { doSomething: jest.fn((cb) => cb('fakeReturnValue');
    });
});

describe('When rendering Parent', () => {
    var parent;

    beforeAll(() => {
        parent = mount(<Parent />)
    });

    it('should display Child with response of the service', () => {
        expect(parent.html()).toMatch('fakeReturnValue')
    });
});

これをどのようにテストすればいいのでしょうか?私はangularがzonejsでこれを解決することを理解していますが、Reactに同等のアプローチはありますか?

どのように解決するのですか?

Jest 27+に更新しました。

jest 27+ではprocess.nextTickも使用可能です。

await new Promise(process.nextTick);

(コメントでAdrian Godongに感謝)

オリジナルの回答

保留中のPromiseが解決されるまで待機するスニペットがあります。

const flushPromises = () => new Promise(setImmediate);

なお setImmediate は非標準の機能であることに注意してください (そして、標準になることは期待されていません)。しかし、もしあなたのテスト環境で十分であれば、良い解決策になるはずです。その説明です。

このメソッドは、長時間実行される処理を分割し、ブラウザがイベントや表示の更新など他の処理を完了した直後にコールバック関数を実行するために使用されます。

async/awaitを使った使い方を大まかに説明します。

it('is an example using flushPromises', async () => {
    const wrapper = mount(<App/>);
    await flushPromises();
    wrapper.update(); // In my experience, Enzyme didn't always facilitate component updates based on state changes resulting from Promises -- hence this forced re-render

    // make assertions 
});

私はこれをよく使いました このプロジェクトでは を使用しました。