MSW(Mock Service Worker)でAPIモックを導入したら、フロントエンド開発がかなり捗った話
バックエンドの実装待ちで詰まっていたフロントエンド開発に MSW を導入したところ、APIモックの管理が一気に楽になり、テストも書きやすくなりました。
🙌 結論から
バックエンドのAPIがまだ完成していないタイミングでフロントエンドを進めるとき、MSW(Mock Service Worker)を導入したらモック管理がかなり楽になりました!
以前は fetch をラップした自前のダミー関数でごまかしていたんですが、条件分岐が増えるたびに崩壊気味になっていて…(´・ω・`)
MSW はネットワークレイヤーでリクエストを横取りしてくれるので、実装コード側は本番とまったく同じ書き方のままモックに切り替えられます👍
💡 MSW とはなにか
MSW は Service Worker(ブラウザ)や Node.js のリクエストインターセプトの仕組みを使って、実際のネットワークリクエストをキャッチしモックレスポンスを返してくれるライブラリです。
fetch や axios の呼び出し側を一切変更しなくていいのが最大の特徴だと思うんですよね(´・∀・)
コンポーネント側は本物のAPIを叩いているつもりのまま、裏側だけモックに差し替わる感じですね(・∀・)
REST はもちろん GraphQL のリクエストにも対応していて、最近のプロジェクト構成ならだいたいカバーできます。
👀 導入してみた
インストールはシンプルです。
npm install msw --save-dev
ハンドラーはこんな感じで定義します。
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/api/users/:id', ({ params }) => {
return HttpResponse.json({ id: params.id, name: 'Taro' })
}),
]
ブラウザ用のワーカースクリプトも1コマンドで生成できます。
npx msw init public/ --save
あとは開発サーバー起動時にワーカーを立ち上げるだけで、Network タブにも普通の通信として表示されます。
✨ 使ってみた感想
一番助かったのは、エラーレスポンスやローディング状態を自由に再現できることです。
500エラーや極端に遅いレスポンスって、実際のバックエンドが動いてる状態だとなかなか意図的に再現しづらくないですか(・_・;)
MSW ならハンドラーの中で delay() を挟んだり、ステータスコードを変えるだけで済みます。
http.get('/api/users/:id', async () => {
await delay(2000)
return HttpResponse.json({ message: 'Server Error' }, { status: 500 })
})
デザイナーへのレビュー依頼でも、バックエンド抜きでほぼ本番同様の画面を見せられるようになったのがだいぶ助かる・・!
🧪 テストでもハンドラーを使い回した
一通り導入して満足していたんですが、しばらくして気づいたのがテストコードとの相性の良さです。
Vitest や Jest のテスト環境でも、同じハンドラー定義をそのまま setupServer に渡せます。
import { setupServer } from 'msw/node'
import { handlers } from './handlers'
export const server = setupServer(...handlers)
開発用に書いたモックがそのままテストの下地になるので、二重管理から解放されたのは正直かなり大きいです✨
コンポーネントテストで「このAPIが失敗したときの表示」を確認したいときも、その場でハンドラーを一時的に上書きするだけで済みました(^^)
パパ系Webエンジニア〜愛用ガジェット一覧 🛍️
この記事を書いている作業環境のガジェットを楽天ROOMにまとめています ✨ 在宅エンジニアのデスク作りの参考にどうぞ 🙌
👍 まとめ
MSW は、ネットワークリクエストをそのままの書き方でモックできるAPIモッキングライブラリです。
バックエンドの実装待ちで止まりがちなフロントエンド開発や、エラー状態のテストがしづらいという悩みには、かなり効果を実感できると思います🙌
まずは開発環境のモックから試してみて、慣れてきたらテストのセットアップにも広げていくのがおすすめです!
※ MSW のAPIやGraphQL対応状況は今も更新が続いています。最新情報は MSW公式ドキュメント をご確認ください👀