React Testing Libraryを使って、関数の中の非同期関数のテストをする。

実装の詳細に依存せずに React コンポーネントをテストすることができるツールセット。
今回は以下のコードをテストする場合の記述について記載します。

typescript
 const handler = useCallback(() => {
      onConfirm?.()
      const fanc = async () => {
        try {
          const addinfo= await addInfo?.(id)
          onCreate?.(addinfo)
        } catch (e) {
          onError?.(e as Error)
        }
      }
      void fanc()
  }, [onConfirm, onCreate, onError])

上記のような関数の中に非同期関数を持つ処理に対して「onConfirm」「onCreate」が呼ばれたかをテストしたいとします。
※ handlerはonClickに設定されているものとします。

typescript

  test('関数の中の非同期関数のテスト', async () => {
    const { getByTestId } = render(
      <TestComponent
        onConfirm={onConfirm}
        onCreate={onCreate}
        onError={onError}
      />
    )  
    void act(() => {
      fireEvent.click(getByTestId('test_element'))
    })
  

    expect(onConfirm).toBeCalled()
    expect(onCreate).toBeCalled()
  })

正気のテストコードでは、非同期のfanc メソッドの処理が終わるのを待たないため、「expect(onCreate).toBeCalled()」に到達した際にonCreateがまだ呼ばれていません。

そんな時にどうしたのか、「waitFor」を使用して解決しました。
waitForは、タイムアウトに到達するまでCallbackを何度も実行することができ、期待値が来るのを待つことができます。これにより、非同期処理でチェックする必要があるテストを実施することができます。

typescript

  test('関数の中の非同期関数のテスト', async () => {
    const { getByTestId } = render(
      <TestComponent
        onConfirm={onConfirm}
        onCreate={onCreate}
        onError={onError}
      />
    )  
    void act(() => {
      fireEvent.click(getByTestId('test_element'))
    })
  
  // タイムアウトまで待つ
    await waitFor(() => expect(onConfirm).toBeCalled())
    await waitFor(() => expect(onCreate).toBeCalled())
  })

注意点として「WaitFor」を使用する場合は、先頭に「await」を記述してください。記述をしないと結果が返る前にテストが終わってしまいます。

まとめ

React Testing Librarを使った関数中の非同期関数のテスト方法注意点

  • 非同期処理を待つ場合は「waitFor」を使う
  • 「waitFor」を使う場合は先頭に「await 」の記述を忘れないこと


コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA