MSW Mock avec Claude Code
Découvrez mSW Mock avec Claude Code. Conseils pratiques et exemples de code inclus.
MSWでリアルなAPIモック環境を構築する
MSW(Mock Service Worker)はService Workerを利用してネットワークレベルでAPIリクエストをインターセプトするモックライブラリです。テストとブラウザ開発の両方で同じモックハンドラーを共有でき、実際のHTTPリクエストと同じ振る舞いを再現します。Claude Codeはハンドラーの設計から型安全なモック構築まで的確にサポートします。
基本的なハンドラー設計
Claude Codeにハンドラーの構成を依頼しましょう。
> MSWでユーザーAPIのモックハンドラーを設計して。
> CRUD操作、エラーハンドリング、レスポンス遅延を含めて。
import { http, HttpResponse, delay } from "msw";
// インメモリデータベース
let users: User[] = [
{ id: "1", name: "Alice", email: "[email protected]", role: "admin" },
{ id: "2", name: "Bob", email: "[email protected]", role: "editor" },
];
export const userHandlers = [
// 一覧取得
http.get("/api/users", async ({ request }) => {
await delay(100);
const url = new URL(request.url);
const page = Number(url.searchParams.get("page") || "1");
const perPage = Number(url.searchParams.get("perPage") || "20");
const search = url.searchParams.get("search") || "";
let filtered = users;
if (search) {
filtered = users.filter(
(u) =>
u.name.toLowerCase().includes(search.toLowerCase()) ||
u.email.toLowerCase().includes(search.toLowerCase())
);
}
const start = (page - 1) * perPage;
const paginated = filtered.slice(start, start + perPage);
return HttpResponse.json({
data: paginated,
meta: { total: filtered.length, page, perPage },
});
}),
// 詳細取得
http.get("/api/users/:id", async ({ params }) => {
await delay(50);
const user = users.find((u) => u.id === params.id);
if (!user) {
return HttpResponse.json(
{ error: "ユーザーが見つかりません" },
{ status: 404 }
);
}
return HttpResponse.json({ data: user });
}),
// 作成
http.post("/api/users", async ({ request }) => {
await delay(200);
const body = (await request.json()) as Omit<User, "id">;
const newUser: User = { ...body, id: String(Date.now()) };
users.push(newUser);
return HttpResponse.json({ data: newUser }, { status: 201 });
}),
// 更新
http.put("/api/users/:id", async ({ params, request }) => {
await delay(150);
const body = (await request.json()) as Partial<User>;
const index = users.findIndex((u) => u.id === params.id);
if (index === -1) {
return HttpResponse.json(
{ error: "ユーザーが見つかりません" },
{ status: 404 }
);
}
users[index] = { ...users[index], ...body };
return HttpResponse.json({ data: users[index] });
}),
// 削除
http.delete("/api/users/:id", async ({ params }) => {
await delay(100);
users = users.filter((u) => u.id !== params.id);
return new HttpResponse(null, { status: 204 });
}),
];
テストでの統合
Vitestとの統合パターンです。
import { setupServer } from "msw/node";
import { userHandlers } from "./handlers/user";
// テスト用サーバー
const server = setupServer(...userHandlers);
beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
describe("UserList コンポーネント", () => {
it("ユーザー一覧を表示する", async () => {
render(<UserList />);
await waitFor(() => {
expect(screen.getByText("Alice")).toBeInTheDocument();
expect(screen.getByText("Bob")).toBeInTheDocument();
});
});
it("APIエラー時にエラーメッセージを表示する", async () => {
// テスト単位でハンドラーを上書き
server.use(
http.get("/api/users", () => {
return HttpResponse.json(
{ error: "サーバーエラー" },
{ status: 500 }
);
})
);
render(<UserList />);
await waitFor(() => {
expect(screen.getByText("データの取得に失敗しました")).toBeInTheDocument();
});
});
it("ネットワークエラー時にリトライボタンが表示される", async () => {
server.use(
http.get("/api/users", () => {
return HttpResponse.error();
})
);
render(<UserList />);
await waitFor(() => {
expect(screen.getByRole("button", { name: "再試行" })).toBeInTheDocument();
});
});
});
ブラウザでの開発用モック
ブラウザ環境でService Workerとして動作させるパターンです。
// src/mocks/browser.ts
import { setupWorker } from "msw/browser";
import { userHandlers } from "./handlers/user";
import { authHandlers } from "./handlers/auth";
export const worker = setupWorker(...userHandlers, ...authHandlers);
// src/main.tsx
async function enableMocking() {
if (import.meta.env.DEV) {
const { worker } = await import("./mocks/browser");
return worker.start({
onUnhandledRequest: "bypass",
});
}
}
enableMocking().then(() => {
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
});
型安全なハンドラー設計
TypeScriptの型とMSWハンドラーを統合するパターンです。
import { http, HttpResponse } from "msw";
// API型定義
interface ApiEndpoints {
"GET /api/users": {
response: { data: User[]; meta: PaginationMeta };
params: never;
};
"GET /api/users/:id": {
response: { data: User };
params: { id: string };
};
"POST /api/users": {
response: { data: User };
body: CreateUserInput;
params: never;
};
}
// ファクトリー関数
function createUserFactory(overrides: Partial<User> = {}): User {
return {
id: String(Math.random()).slice(2, 10),
name: `User ${Math.random().toString(36).slice(2, 6)}`,
email: `user-${Date.now()}@example.com`,
role: "viewer",
...overrides,
};
}
// テストシナリオ用のハンドラーセット
export const emptyStateHandlers = [
http.get("/api/users", () =>
HttpResponse.json({ data: [], meta: { total: 0, page: 1, perPage: 20 } })
),
];
export const errorHandlers = [
http.get("/api/users", () =>
HttpResponse.json({ error: "Internal Server Error" }, { status: 500 })
),
];
export const slowResponseHandlers = [
http.get("/api/users", async () => {
await delay(5000);
return HttpResponse.json({ data: [createUserFactory()], meta: { total: 1, page: 1, perPage: 20 } });
}),
];
Summary
MSWはネットワークレベルのモックにより、実際のAPI通信に近い環境でテストと開発ができます。Claude Codeを活用すれば、ハンドラー設計、テスト統合、型安全な構成を短時間で構築可能です。
ユニットテストとの連携はVitest上級テクニックを、E2Eテストでの活用はPlaywright E2Eテスト実践ガイドを参照してください。MSW公式ドキュメントも確認しておきましょう。
PDF gratuit : aide-mémoire Claude Code en 5 minutes
Laissez simplement votre e-mail et nous vous enverrons immédiatement l'aide-mémoire A4 en PDF.
Nous traitons vos données avec soin et n'envoyons jamais de spam.
À propos de l'auteur
Masa
Ingénieur passionné par Claude Code. Il gère claudecode-lab.com, un média tech en 10 langues avec plus de 2 000 pages.
Articles similaires
7 templates CLAUDE.md pour Claude Code à copier dans de vrais projets
Sept templates CLAUDE.md pratiques pour appli solo, site de contenu, API, repo d'équipe et code legacy, avec les erreurs à éviter.
Guide Approval et Sandbox pour Claude Code | Reglages surs pour le travail quotidien
Comment repartir les actions de Claude Code entre allow, ask, deny et sandbox avec des settings utiles, des hooks et des cas reels.
Guide complet pour débuter avec Claude Code 2026 | 7 étapes pour passer de zéro à une utilisation professionnelle
Le guide de démarrage complet pour les nouveaux utilisateurs de Claude Code. De l'installation à l'intégration dans un vrai workflow de développement — avec tous les pièges que Masa a rencontrés au début.