🕌

React Query-テスト編

2022/08/01に公開

TanStack | High Quality Open-Source Software for Web Developers

React Query について公式ドキュメントを読みながら自分に必要なものをまとめたメモを記事化したもので以下の 4 つの記事で構成されています。記事ができたものから順次リンク化していきます。

参考記事

Testing | TanStack Query Docs
API | Testing Library
MSW – Seamless API mocking library for browser and Node | Mock Service Worker

Testing React Query | TkDodo's blog
ReactQueryを用いたhooksのテストを書きたい
react-query : useQuery への依存をスタブに差し替えてコンポーネントテスト

準備

render や renderHook が使えるようにパッケージ追加

npm install @testing-library/react @testing-library/react-hooks react-test-renderer --save-dev

ネットワークアクセスに関しては MSW を使うと本来の動きをシミューレートできる

npm install msw --save-dev

Wrapper

基本的にはテスト対象を以下のように QueryClientProvider の中に配置する

const queryClient = new QueryClient()
render(
  <QueryClientProvider client={queryClient}>
    <TestComponent />
  </QueryClientProvider>
)

hooks のテストに使う renderHook は options の wrapper を使う必要がある
ちなみにこの wrapper は render にも同じ方法で使える

const queryClient = new QueryClient()
const queryWrapper = ({children}:QueryWrapperProps) => {
  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  )
}
const {result} = renderHook(() => useHooks(), { wrapper: queryWrapper })

QueryClient を使いたい場合も多いので以下のような create 関数を用意すると便利。 ついでに retry なし & 自動再取得なしにしている。

import { ReactElement } from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

export const createQueryWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
        staleTime: Infinity
      }
    }
  })
  const queryWrapper = ({children}: {children: ReactElement}) => {
    return (
      <QueryClientProvider client={queryClient}>
        {children}
      </QueryClientProvider>
    )
  }
  return { queryClient, queryWrapper }
}

使い方

import { createQueryWrapper } from './testWrapper'

// queryClient が不要なら受け取らない
const { queryWrapper } = createQueryWrapper()
render(<TestComponent />, { wraper: queryWrapper })
renderHook(() => useHooks, { wraper: queryWrapper })

Tips

QueryClient を使ってキャッシュを登録し API アクセス不要にする

const { queryClient, queryWrapper } = createQueryWrapper()
queryClient.setQueryData(['users'], {
  [{
    id:   'test_id_1',
    name: 'test_name_1',
    age:  20,
  }]
})
render(<TestComponent />, {wrapper: queryWrapper})

コンポーネントを描画する関数を提供する hooks の場合は render 側で使う

const { result } = renderHook(() => useComponent())
render(result.current(), { wrapper: queryWrapper})

データの取得待ち

const {result} = renderHook(() => useUsers(), {wrapper: queryWrapper})
// 変数の場合
await waitFor(() => !!result.current.users)
// 要素の場合(find系を使う)
const target = await screen.findByText('username')

Discussion