Mock Service Workerを利用したGraphQL開発環境構築
GraphQLサーバー構築が間に合わない、先にフロントエンド開発しておきたいという時ってありますよね。
そんな時に Mock Service Worker(以下、MSWと略) を使用してモック環境作成が可能です。
今回はMSW+GraphQLの環境構築をご紹介します。
環境
"msw": "^1.0.1"
"@mswjs/data": "^0.11.2"
"react": "^18.2.0"
"@apollo/client": "^3.7.7"
MSWについて
実際にモックサーバーを立ち上げるわけではなく、サービスワーカーレベルでリクエストを奪い、レスポンスを返すようになります。
実際のAPIを叩かないので、サーバー負荷をかけることがなく、サーバー状態でAPIが使用できなくなることもなくなります。Reactプロジェクト作成
Reactプロジェクトを作成します。ここではTypeScriptを使用することにします。
npx create-react-app myapp --template typescript
モックサーバーの作成
実際にMSWを使用して、モックサーバーを作成しましょう。
mswjs/data
mswjs/data
ライブラリを使用してハンドラを立てていきます。
以下、公式の説明です。
ハードコーディングされた一連のフィクスチャを保持する代わりに、このライブラリは、データ駆動型 API モックに必須のツールを提供します。
https://github.com/mswjs/data#motivation
簡単にいうと、mswjs/data
を使えば仮想DBをブラウザ展開して、実際のDBを扱うように操作できるよっていう感じでしょうか。
ハンドラ登録
factory
関数を使用しデータをモデリングしていきます。
import { factory, primaryKey } from "@mswjs/data";
const db = factory({
todo: {
id: primaryKey(String),
title: String,
},
});
export const handlers = [...db.todo.toHandlers("graphql")];
ここでtoHandlers
が出てきました。これも便利なAPIの1つです。
todo
モデルに対し、以下のように自動でCRUDハンドラが生成されます。
- todo(where: TodoQueryInput): Todo
- createTodo(data: TodoInput!): Todo!
- updateTodo(where: TodoQueryInput!, data: TodoInput!): Todo!
- deleteTodo(where: TodoQueryInput!): Todo!
このAPIを使えばCRUDハンドラを簡単構築できます。
以下のように、自分で定義が可能です。
export const handlers = [
graphql.query('GetTodo', (req, res, ctx) => {
return res(ctx.data({
todos: db.todo.getAll()
}))
}),
]
ハンドラ設定
ブラウザ、Node.js環境で使用するハンドラ設定をします。
import { setupWorker } from "msw";
import { handlers } from "./handlers";
export const worker = setupWorker(...handlers);
import { setupServer } from "msw/node";
import { handlers } from "./handlers";
export const server = setupServer(...handlers);
Service Workerの生成
さいごにMSWが使用するService Workerを生成する必要があります。
今回はpublic公開ディレクトリに作成します。
npx msw init public --save
するとpublic/mockServiceWorker.js
が作成されます。
開発環境で起動してみる
開発モードのみ使用したいので、環境変数を利用します。
...
if (process.env.NODE_ENV === "development") {
const { worker } = require("./mocks/browser");
worker.start();
}
...
実際に起動させてみます。
するとワーカーが立ち上がっているのがコンソールで確認できます。
テスト起動
Node.js環境なので、先ほど作成したserver.ts
を使用します。
テスト毎にモックサーバーが立ち上がり、終われば停止させるように設定します。
...
import { client } from "./libs/apollo";
import { server } from "./mocks/server";
beforeAll(() => {
server.listen();
});
beforeEach(() => {
return client.clearStore();
});
afterEach(() => {
server.resetHandlers();
});
afterAll(() => {
server.close();
});
シーディング
モックデータを生成したい場合にはORM風にデータ生成が可能です。
const db = factory({
todo: {
id: primaryKey(String),
title: String,
},
});
for (let i = 0; i < 3; i++) {
db.todo.create({
id: Math.random().toString(32).substring(2) ,
title: `todo-${i}`
})
}
さいごに
MSWはテスト環境だけでなく開発環境などでも使用できます。
REST APIだけでなくGraphQLのモック環境も作成できるので、ぜひ活用してみてください。
作成リポジトリ
今回作成したコードを載せています。
参考記事
Discussion