MSW2.0(Mock Service Worker)の使い方 ~②実践編~
2024/4/10
msw
React
swr
はじめに
本記事は、MSW2.0(Mock Service Worker)の使い方 ~①環境構築編~ の続きとなりまして、mswの基本的な使い方を紹介しています。
環境構築を終えている前提で進みますので、まだ目を通していない方は、上記記事を先にご確認ください。
- 環境構築編 ← MSW2.0(Mock Service Worker)の使い方 ~①環境構築編~
- 実践編 ← 本記事の内容
学べる事
- mswの基本的な使い方
- mswの実践的な使い方
動作環境
- Node: v20.7.0
- Vite: ^5.2.0
- React(TypeScript): ^18.2.0
- msw: ^2.2.3
- swr: ^2.2.5
ソースコード
今回説明に作成したサンプルアプリはGithubにて公開しています。
https://github.com/kentechn/react-msw-sample-app
基本的な使い方
今回は、以下apiのモック作成を通じて、使い方を解説していきます。
- GET /api/users -> ユーザーリストの取得
- GET /api/users/[userId] -> userIdに紐づくユーザーの取得
- POST /api/users -> ユーザーの新規作成
GETリクエストのモック定義方法
import { HttpResponse, http } from "msw";
type User = {
id: number;
name: string;
};
const userList: User[] = [
{ id: 1, name: "テストユーザー1" },
{ id: 2, name: "テストユーザー2" },
{ id: 3, name: "テストユーザー3" },
{ id: 4, name: "テストユーザー4" },
];
export const handlers = [
// ユーザー一覧取得api
http.get("/api/users", () => {
return HttpResponse.json(userList);
})
];
パスパラメータの取得
userListの中から、パスパラメータのuserIdに紐づくユーザーをレスポンスとして返します
export const handlers = [
...,
// 特定のユーザー取得api
http.get("/api/users/:userId", ({params}) => {
const userId = Number(params.userId)
const user = userList.filter((item) => {
return item.id === Number(userId)
})[0]
return HttpResponse.json(user);
}),
];
リクエストボディの取得
await request.json()
でformデータを取得します。今回は、bodyが空のレスポンスを返しています。
// 追記
type CreateUserFormData = Pick<User, "name">;
export const handlers = [
...,
// ユーザー作成api
http.post("/api/users", async ({ request }) => {
const body = (await request.json()) as CreateUserFormData;
const newUser: User = { id: userList.length + 1, name: body.name };
userList.push(newUser);
// 空のレスポンスを返却
return new HttpResponse(null, {
status: 201,
statusText: "success",
});
}),
];
クエリパラメータの取得
await request.url()
でurlを取得し、searchParams.get("パラメータkey名")
で対象のクエリパラメータを取得します。
先ほど定義したGET /api/usersのモックAPIを、nameというクエリパラメータでfilteringするよう修正します。
export const handlers = [
// ユーザー一覧取得api
http.get("/api/users", ({ request }) => {
const url = new URL(request.url);
const userName = url.searchParams.get("name");
if (!userName) {
return HttpResponse.json(userList);
}
const filteredUserList = userList.filter((user) => {
return user.name === userName;
});
return HttpResponse.json(filteredUserList);
}),
...
]
?id=1&id=2&id=3のように、複数同じkeyが存在する場合は、
searchParams.get("id") -> searchParams.getAll("id")
とすることで、idの値を全て取得できます。
エラーハンドリング
nullのところに、エラー用のレスポンスボディを含めることもできます。
return new HttpResponse(null, {
status: 404,
statusText: "エラーメッセージ",
});
// or
return HttpResponse.json(null, {
status: 404,
statusText: "エラーメッセージ",
});
cookieの取得、送信
リクエストのcookieは、cookies.プロパティ名
で取得できます。
レスポンスにcookieを含める場合、headerオプションに'Set-Cookie': 'key=value'
内を追記します。
http.get("resource", async ({ cookies }) => {
// cookieの値を取得
console.log(cookies.mySecret)
// cookieの送信
return HttpResponse.json(null, {
status: 201,
statusText: "success",
headers: {
'Set-Cookie': 'mySecret=abc-123'
}
});
}),
まとめ
今回作成したhandlerは以下になります。
import { HttpResponse, http } from "msw";
type User = {
id: number;
name: string;
};
type CreateUserFormData = Pick<User, "name">;
const userList: User[] = [
{ id: 1, name: "テストユーザー1" },
{ id: 2, name: "テストユーザー2" },
{ id: 3, name: "テストユーザー3" },
{ id: 4, name: "テストユーザー4" },
];
export const handlers = [
// ユーザー一覧取得api
http.get("/api/users", ({ request }) => {
const url = new URL(request.url);
const userName = url.searchParams.get("name");
if (!userName) {
return HttpResponse.json(userList);
}
const filteredUserList = userList.filter((user) => {
return user.name === userName;
});
return HttpResponse.json(filteredUserList);
}),
// 特定のユーザー取得api
http.get("/api/users/:userId", ({ params }) => {
const userId = Number(params.userId);
if (!userId) {
return HttpResponse.json(null, {
status: 400,
statusText: "bad request",
});
}
const user = userList.filter((user) => {
return user.id === Number(userId);
})[0];
if (!user) {
return HttpResponse.json(null, {
status: 404,
statusText: "no resource",
});
}
return HttpResponse.json(user);
}),
// ユーザー作成api
http.post("/api/users", async ({ request }) => {
const body = (await request.json()) as CreateUserFormData;
const newUser: User = { id: userList.length + 1, name: body.name };
userList.push(newUser);
return HttpResponse.json(null, {
status: 201,
statusText: "success"
});
}),
// cookie取得解説用Api(利用なし)
http.get("resource", async ({ cookies }) => {
console.log(cookies.mySecret);
return HttpResponse.json(null, {
status: 201,
statusText: "success",
headers: {
"Set-Cookie": "mySecret=abc-123",
},
});
}),
];
プロフィール
タグ一覧