フロントエンドのテストを書いているなら、Mock Service Worker(MSW)は有力な選択肢です。MSWはブラウザやNode.js内でリクエストをインターセプトし、ユニットテストやコンポーネントテストを安定させます。一方で、チーム間で共有するモック、非JavaScriptクライアント、OpenAPI起点のモック生成が必要になると、ホスト型APIモックプラットフォームの方が扱いやすい場面があります。
Mock Service Workerとは?
Mock Service Workerは、ネットワークリクエストをアプリケーションコードの近くでインターセプトするJavaScriptライブラリです。
ブラウザではService Workerを登録し、送信されるfetchやXMLHttpRequestを捕捉します。Node.jsではリクエストレイヤーにパッチを適用することで、JestやVitestなどのテスト環境でも同じハンドラーを実行できます。
アプリケーションコードは通常どおり実APIを呼び出します。MSWがその途中でレスポンスを返すため、fetchを直接スタブしたり、HTTPクライアントを差し替えたりする必要はありません。
インターセプション層の実装に興味がある場合は、GitHubのMSWソースを確認できます。
典型的なハンドラーは次のようになります。
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/api/users/:id', ({ params }) => {
return HttpResponse.json({
id: params.id,
name: 'Ada Lovelace',
})
}),
]
テスト側では、アプリケーションが/api/users/1へリクエストしたときに、MSWが定義済みのJSONを返します。モックはコードの隣に置けるため、テストと一緒にバージョン管理しやすいのが大きな利点です。
MSWが向いているケース
MSWは、モックを使うコードとモック定義が同じリポジトリにある場合に特に有効です。
1. コンポーネントテスト・ユニットテスト
ReactやVueのコンポーネントをレンダリングし、実際にHTTPリクエストを発行させたうえで、MSWが固定レスポンスを返します。
import { render, screen } from '@testing-library/react'
import { UserProfile } from './UserProfile'
test('ユーザー名を表示する', async () => {
render(<UserProfile userId="1" />)
expect(await screen.findByText('Ada Lovelace')).toBeInTheDocument()
})
HTTPクライアントを直接モックする方法と比較したい場合は、API呼び出しのJestモックも参考になります。
2. ローカルでのフロントエンド開発
バックエンドが未完成でも、MSWでレスポンスを定義すればUI開発を進められます。
たとえば、状態ごとにハンドラーを切り替えます。
http.get('/api/users', () => {
return HttpResponse.json([
{ id: '1', name: 'Ada Lovelace' },
{ id: '2', name: 'Grace Hopper' },
])
})
エラー状態を確認したい場合は次のようにします。
http.get('/api/users', () => {
return new HttpResponse(null, { status: 500 })
})
これにより、ローディング、空配列、権限エラー、サーバーエラーなどをローカルで再現できます。
3. 決定論的なCI
MSWを使うと、テストはライブサーバーや共有ステージング環境に依存しません。
そのため、次のようなCIの不安定要因を減らせます。
- ネットワーク遅延
- ステージングデータの変更
- 外部APIの一時的な障害
- 認証トークンの期限切れ
4. 1つの言語・1つのチームで完結する開発
モックを書く人と使う人が同じフロントエンドチームであれば、MSWのハンドラーをリポジトリ内に置くのがシンプルです。
このケースでは、MSWだけで十分なことが多いです。MSWは無料のオープンソースであり、フロントエンドテストとローカル開発に適しています。
MSWが限界に達しやすいケース
MSWの強みは「JavaScriptコードとしてリポジトリ内に置けること」です。ただし、チームや利用者が増えると、この特徴が制約になる場合があります。
1. 非JavaScriptコンシューマーがいる
MSWのハンドラーはJavaScriptです。
そのため、次のようなチームはMSWのハンドラーをそのまま使えません。
- Swiftで実装するiOSチーム
- Kotlinで実装するAndroidチーム
- GoやPythonで統合テストを書くバックエンドチーム
- 外部パートナーのクライアントアプリ
この場合、各チームが別々にモックを作ることになり、レスポンスの形やエラーケースがズレやすくなります。
HTTP経由でアクセスできる言語非依存のモックサーバーであれば、どの言語のクライアントからでも同じモックを利用できます。
2. 共有URLとして常時使いたい
MSWは基本的にプロセス内で動きます。
つまり、QAエンジニア、デザイナー、モバイルチーム、外部パートナーが同じURLにアクセスして使う、という用途には向いていません。
共有モックが必要な場面の例です。
- QAが同じテストデータで画面確認したい
- デザイナーが実装中UIを固定レスポンスで確認したい
- モバイルチームがバックエンド完成前にAPI連携を進めたい
- 複数チームが同じエンドポイント仕様を確認したい
この場合は、Service Workerではなく、安定したURLを持つホスト型モックサーバーが必要になります。
3. OpenAPI起点でAPIを設計している
APIをコードより先にOpenAPIで設計する場合、モックもその仕様から生成できる方が安全です。
MSWでは、基本的にハンドラーを手で書きます。
http.post('/api/orders', async ({ request }) => {
const body = await request.json()
return HttpResponse.json({
id: 'order_123',
status: 'created',
total: body.total,
})
})
この方法は柔軟ですが、OpenAPIスキーマと手書きハンドラーがズレる可能性があります。
スキーマからモックを直接生成するワークフローについては、APIモックに関するガイドも参考になります。
4. リアルな動的データを大量に返したい
MSWは、ハンドラーに書いた内容を返します。
少数のレスポンスであれば問題ありませんが、次のようなケースでは手書きが重くなります。
- 多数のフィールドを持つレスポンス
- ページネーション
- リスト、詳細、検索結果の組み合わせ
- 日付、メールアドレス、IDなどの現実的な値
- 複数のエラーケース
fakerのような生成ロジックを自前で書くこともできますが、レスポンス設計が増えるほど管理コストが上がります。
フィールド名からデータを推測して生成できるプラットフォームを使うと、emailにはメールアドレス、createdAtには日付のように、より現実的なモックを作りやすくなります。
MSWとホスト型APIモックプラットフォームの比較
どちらが常に優れている、という話ではありません。解決する問題が異なります。
| 機能 | Mock Service Worker | ホスト型APIプラットフォーム(例: Apidog) |
|---|---|---|
| JSユニットテスト/コンポーネントテスト内で実行 | はい、ネイティブ | いいえ、JSテストライブラリではありません |
| HTTP経由で言語非依存に利用 | いいえ、基本的にJS向け | はい、あらゆるクライアントから利用可能 |
| チーム全体で共有されるURL | いいえ | はい、ホスト型モックサーバー |
| OpenAPIからモックを生成 | 手動 | スキーマから自動 |
| スマート/動的データ生成 | 手動でコーディング | 組み込み |
| テストとともにリポジトリ内で管理 | はい | 共有プロジェクトに保存 |
| コスト | 無料、オープンソース | 無料枠 + 有料プラン |
結論として、MSWはフロントエンドテストやローカル開発に適しています。Apidogのようなプラットフォームは、モックを共有したい場合、言語非依存で使いたい場合、または仕様駆動で生成したい場合に適しています。
ApidogはMSWの置き換えではなく補完
Apidogは、JestやVitest内でMSWの代わりにインポートするライブラリではありません。
つまり、次のように使うものではありません。
// Apidogをテストランナー内でMSWのように起動する、という使い方ではない
Apidogは、テストランナーの外側で使うホスト型プラットフォームです。共有された、言語非依存の、スキーマ駆動型モックを提供する層として考えると整理しやすくなります。
実装上の使い分け
実務では、次のように分けると扱いやすいです。
MSWを使う場所
- フロントエンドリポジトリ内のユニットテスト
- コンポーネントテスト
- ローカル開発中の一時的なレスポンス切り替え
- React/VueなどJSアプリ内で完結するモック
Apidogのようなホスト型モックを使う場所
- フロントエンド、モバイル、QAで同じモックURLを使う
- Swift、Kotlin、Go、Pythonなど非JSクライアントから使う
- OpenAPIからモックを生成する
- API仕様、ドキュメント、テスト、モックを同じスキーマに寄せる
- デモやレビュー用に常時アクセス可能なモックを用意する
Apidogでの基本的な流れ
Apidogを使う場合の大まかな流れは次のとおりです。
- APIを設計する、またはOpenAPIをインポートする
- スキーマからモックエンドポイントを生成する
- 生成されたモックURLをフロントエンド、モバイル、QAに共有する
- 必要に応じて特定のエラーやエッジケースをカスタムする
- API仕様の変更に合わせてモックを更新する
たとえば、emailというフィールドにはメールアドレス、createdAtには日付のように、フィールド名から推測した現実的なデータを返せます。特定の500エラーや境界値を再現したい場合は、カスタムルールを追加して調整します。
モックが設計やテストと同じスキーマから派生するため、手書きハンドラーよりも契約とのズレを抑えやすくなります。
スキーマからモックへの生成を他ツールと比較したい場合は、最高のAPIモックツールの比較も参考になります。
既存のMSW設定と並行してホスト型モックを試したい場合は、Apidogをダウンロードできます。
他のMSW代替手段
MSW以外にも、モックを作る方法はいくつかあります。スタックや目的に応じて選びます。
- Mockoon: GUIでローカルモックサーバーを素早く立ち上げるデスクトップアプリ
- WireMock: Javaベースのモックサーバー。JVMチームや契約テストで使いやすい
- Prism by Stoplight: OpenAPIファイルからCLI経由でモックを生成
- json-server: JSONファイルを簡易REST APIとして公開するプロトタイピング向けツール
選び方の目安は次のとおりです。
| 目的 | 選択肢 |
|---|---|
| JSのコンポーネントテスト | MSW |
| GUIで素早くローカルモック | Mockoon |
| JVM中心の契約テスト | WireMock |
| OpenAPIからCLIでモック生成 | Prism |
| JSONから簡易REST API | json-server |
| チーム全体で共有するホスト型モック | ApidogなどのAPIプラットフォーム |
もし課題が「MSWでは非JSチームメイトを助けられない」ことであれば、HTTPベースのモックサーバーが解決策になります。
ReactでAxiosを使う場合の実装例については、ReactでAxiosを使ってAPIをモックする方法も参考になります。
よくある質問
MSWは無料ですか?
はい。Mock Service WorkerはMITライセンスのオープンソースであり、商用・非商用を問わず無料で使用できます。
共有モックのためにホスト型プラットフォームを使う場合は、ツールによって無料枠や有料プランがあります。Apidogにも無料枠があります。
ApidogはユニットテストでMSWの代わりになりますか?
いいえ。ApidogをMSWのドロップイン置き換えとして使うべきではありません。
MSWはJavaScriptのテストランナー内でリクエストをインターセプトします。一方、Apidogはホスト型プラットフォームであり、JestやVitestにインポートして使うライブラリではありません。
テストランナー内だけに焦点を当てる場合は、API呼び出しをモックする方法でコードベースのアプローチを確認できます。
MSWはNode.jsでも動作しますか?
はい。ブラウザとNode.jsの両方で動作します。
ブラウザではService Workerを使用します。Node.jsではリクエストレイヤーにパッチを適用し、Jest、Vitest、その他のNode.jsテスト環境で同じハンドラーを実行できます。
このデュアルモードは、JavaScript中心のチームにとってMSWの大きな強みです。
MSWからホスト型モックサーバーに切り替えるべきタイミングは?
完全に切り替えるというより、必要な場面で追加するのが現実的です。
次の兆候があれば、ホスト型モックサーバーの導入を検討できます。
- 非JavaScriptクライアントが同じモックを使いたい
- 複数人が同じ安定したURLを必要としている
- QAやデザイナーにもモックを共有したい
- APIをOpenAPIファーストで設計している
- スキーマからモックを自動生成したい
まとめ
MSWは、JavaScript内でフロントエンドやユニットテストのリクエストをインターセプトする用途に非常に適しています。
一方で、MSWは共有されたホスト型モックサーバーでも、言語非依存のAPIプラットフォームでもありません。そこを無理に担わせる必要はありません。
実務では、次のように分けるのが効果的です。
- フロントエンドリポジトリ内のテストにはMSWを使う
- チーム間共有、非JSクライアント、OpenAPI起点のモックにはホスト型APIモックを使う
Apidogは、共有されたスキーマ駆動型モックを扱うための選択肢です。実URLを持つホスト型モックサーバー、OpenAPI設計からの自動モック、現実的なデータ生成を提供します。
MSWが得意な場所ではMSWを使い続け、テストランナーの境界を越えるモックはApidogのようなプラットフォームに任せると、チーム全体で扱いやすいモック環境を作れます。
Top comments (0)