【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をプロジェクトに導入する手順は以下の通り。

  1. MSWのインストール:

    1npm install msw --save-dev
  2. ハンドラーの作成:

    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形式のユーザーデータのモックレスポンスを返す。

  3. テストサーバーの構成:

    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を動作させるためのサーバーインスタンスを作成する。

  4. 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のQueryClientProviderUserListコンポーネントをラップし、テスト環境でReact Queryが利用できるようにする。render関数でUserListコンポーネントをレンダリングし、ローディング表示がされていることを確認した後、waitFor関数を使用して、モックされたAPIエンドポイントから取得したユーザーリストが表示されるまで待機する。

MSWを使用する利点は、APIとの統合テストをより現実的に行えること、React Queryのキャッシュ、リフェッチ、ステータス管理などの機能をテストできること、成功、エラー、ローディング、遅延などの様々なケースをカバーできること、そして、E2Eテスト(Playwright/Cypress)で利用できる再利用性の高いモックを作成できることである。

結論として、React Queryを使用する際には、useQueryを直接モックするのではなく、MSWを使用してAPIエンドポイントをモックすることで、より信頼性が高く、保守しやすいテストを構築できる。

【ITニュース解説】Mockando Endpoints com MSW em Testes com Jest e React Query | いっしー@Webエンジニア