【ITニュース解説】Mockando Endpoints com MSW em Testes com Jest e React Query
2025年09月05日に「Dev.to」が公開したITニュース「Mockando Endpoints com MSW em Testes com Jest e React Query」について初心者にもわかりやすいように丁寧に解説しています。
ITニュース概要
React Query利用時、テストで`useQuery`を直接mockすると、キャッシュやエラー処理がテストされない。MSW(Mock Service Worker)を使うと、APIエンドポイントをmockし、React Queryの機能を維持できる。MSWは実際のAPIリクエストをインターセプトし、mockデータで応答する。Jestと組み合わせることで、ローディング、成功、エラー等の状態をテスト可能になる。これにより、より現実的で信頼性の高いテストが実現する。
ITニュース解説
この記事では、React Queryを使用するReactアプリケーションのテストにおいて、MSW (Mock Service Worker) を用いてAPIエンドポイントをモックする方法について解説する。React Queryは、キャッシュ、自動リフェッチ、エラーハンドリングなど、多くの便利な機能を提供するライブラリだが、テストでuseQueryを直接モックすると、これらの機能が十分にテストされず、脆弱なテストになりがちである。
useQueryを直接モックする例として、以下のコードが挙げられる。
1jest.mock('@tanstack/react-query', () => ({ 2 useQuery: () => ({ data: [{ id: 1, name: 'Test' }], isLoading: false }), 3}));
この方法では、React Queryのキャッシュやリフェッチのメカニズムがテストされず、ローディングやエラーの状態も再現できない。また、コンポーネントとテストが強く結びついてしまい、コンポーネントの変更がテストに大きな影響を与える可能性がある。
より良いテスト方法として、MSWを使用してAPIエンドポイントをモックする方法が推奨されている。MSWは、ブラウザまたはNode.jsで動作するService Worker APIを使用して、ネットワークリクエストをインターセプトし、モックされたレスポンスを返す。これにより、React Queryのキャッシュ、リフェッチ、エラーハンドリングなどの機能を維持したまま、APIとの統合テストが可能になる。
MSWをプロジェクトに導入する手順は以下の通り。
-
MSWのインストール:
1npm install msw --save-dev -
ハンドラーの作成:
src/mocks/handlers.tsなどのファイルを作成し、モックするAPIエンドポイントとレスポンスを定義する。1// src/mocks/handlers.ts 2import { rest } from 'msw'; 3 4export const handlers = [ 5 rest.get('/api/users', (req, res, ctx) => { 6 return res( 7 ctx.status(200), 8 ctx.json([{ id: 1, name: 'Rayza' }, { id: 2, name: 'Vitor' }]) 9 ); 10 }), 11];この例では、
/api/usersへのGETリクエストをインターセプトし、ステータスコード200とJSON形式のユーザーデータのモックレスポンスを返す。 -
テストサーバーの構成:
src/mocks/server.tsなどのファイルを作成し、MSWのサーバーをセットアップする。1// src/mocks/server.ts 2import { setupServer } from 'msw/node'; 3import { handlers } from './handlers'; 4 5export const server = setupServer(...handlers);setupServer関数は、Node.js環境でMSWを動作させるためのサーバーインスタンスを作成する。 -
Jestとの統合:
src/setupTests.tsなどのファイルを作成し、JestのライフサイクルにMSWのサーバーを統合する。1// src/setupTests.ts 2import '@testing-library/jest-dom'; 3import { server } from './mocks/server'; 4 5beforeAll(() => server.listen()); 6afterEach(() => server.resetHandlers()); 7afterAll(() => server.close());beforeAllでサーバーを起動し、afterEachで各テストの後にハンドラーをリセットし、afterAllでサーバーを停止する。さらに、
jest.config.tsに以下の設定を追加する。1setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],これにより、Jestがテスト実行前に
src/setupTests.tsを実行し、MSWのサーバーが適切に設定される。
これらの手順を踏むことで、MSWを使用してAPIエンドポイントをモックし、React Queryの機能を維持したまま、より現実的なテストを実施できる。
具体的なテストの例として、ユーザーリストを表示するコンポーネントUserListのテストケースを示す。
1// UserList.tsx 2import { useQuery } from '@tanstack/react-query'; 3import axios from 'axios'; 4 5export function UserList() { 6 const { data, isLoading, error } = useQuery(['users'], async () => { 7 const res = await axios.get('/api/users'); 8 return res.data; 9 }); 10 11 if (isLoading) return <p>Loading...</p>; 12 if (error) return <p>Error!</p>; 13 14 return ( 15 <ul> 16 {data.map((user: any) => ( 17 <li key={user.id}>{user.name}</li> 18 ))} 19 </ul> 20 ); 21}
1// UserList.test.tsx 2import { render, screen, waitFor } from '@testing-library/react'; 3import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; 4import { UserList } from './UserList'; 5 6const queryClient = new QueryClient(); 7 8function renderWithClient(ui: React.ReactElement) { 9 return render( 10 <QueryClientProvider client={queryClient}>{ui}</QueryClientProvider> 11 ); 12} 13 14test('renders user list from mocked endpoint', async () => { 15 renderWithClient(<UserList />); 16 17 expect(screen.getByText(/loading/i)).toBeInTheDocument(); 18 19 await waitFor(() => { 20 expect(screen.getByText('Rayza')).toBeInTheDocument(); 21 expect(screen.getByText('Vitor')).toBeInTheDocument(); 22 }); 23});
このテストでは、renderWithClient関数を使用して、React QueryのQueryClientProviderでUserListコンポーネントをラップし、テスト環境でReact Queryが利用できるようにする。render関数でUserListコンポーネントをレンダリングし、ローディング表示がされていることを確認した後、waitFor関数を使用して、モックされたAPIエンドポイントから取得したユーザーリストが表示されるまで待機する。
MSWを使用する利点は、APIとの統合テストをより現実的に行えること、React Queryのキャッシュ、リフェッチ、ステータス管理などの機能をテストできること、成功、エラー、ローディング、遅延などの様々なケースをカバーできること、そして、E2Eテスト(Playwright/Cypress)で利用できる再利用性の高いモックを作成できることである。
結論として、React Queryを使用する際には、useQueryを直接モックするのではなく、MSWを使用してAPIエンドポイントをモックすることで、より信頼性が高く、保守しやすいテストを構築できる。