Closed
6

MSW の素振り

概要

  • MSW を使った API モックを雑に試す
  • Vite で立ち上げた Vue3 アプリケーションを使ってる

MSW について

MSW (Mock Service Worker) は、 ネットワークレベルで API をモックするための npm パッケージ。

ネットワークレベルというのが特徴で、利用側がモックの存在を意識せずとも、そのままのコードで API レスポンスだけを差し替えることができる。

利用側のコードを書き換える必要がないため、一つのモックで、開発環境、テスト環境、あるいは Storybook のようなサンドボックス環境でもそのまま利用することができる

素振り用のアプリを用意する

今回は、Vueアプリケーションの開発環境上で、サーバサイドが未完成のため、MSW によるモックを用いた開発をするという想定で試してみる。

単に素振り用 Vue アプリケーションがあれば充分なので、 Vite で開発環境を用意する。

$ yarn create @vitejs/app msw-test --template vue-ts

開発環境をセットアップして立ち上げる。必要なパッケージをついでに追加しておく。

$ cd msw-test
$ yarn install
$ yarn add axios
$ yarn add -D prettier
$ yarn dev

スキャフォールドされた App.vue を最低限の内容に書き換える

App.vue
<template>
  <div>Hello, MSW!!</div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  name: "App",
});
</script>

これで準備OK

MSW のインストール

msw は開発、テスト用途なので devDependencies でインストール

$ yarn add -D msw

REST API のモックを作成する

msw は、 REST API または GraphQL API のモックを作成することができるが、本スクラップでは REST のみを扱う。

src/mocks/handlers.ts を作成し、ここに全てのモックの定義をまとめて書いていく。

src/mocks/handlers.ts
import { rest } from 'msw'

export const handlers = [
  rest.get('/users', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({
        users: [
          {
            id: 1,
            name: 'suzuki'
          },
          {
            id: 2,
            name: 'sato'
          }
        ]
      })
    )
  })
]

直感的に読めると思うが、ここでは /users にGET リクエストした際に、ステータスコード200で、2種類のユーザー情報を返却するようなモックを定義した

モックを ブラウザから利用する

モックの定義が完了したので、次はこれをブラウザ上で Service Worker を使って動かしていく。

なお、 MSW は Node 上でも動かすことが出来るが、 Node では Service Worker が使えないため、別の方法を用いることになるが、ここではブラウザ上でのみ動作確認を行う。

ワーカーのセットアップ

ここで立ち上げる Service Worker は、ブラウザ上でのリクエストを仲介し、モックレスポンスに差し替える役割を持つ。

そのために、ワーカーのコードを配置する必要があるが、これを自分で書くのは困難なので、 以下コマンドを用いて MSW から提供されるコードを複製する。

$ npx msw init public/ --save

これによって、 public/ ディレクトリに、ワーカーコードが作成される。 public/ ディレクトリはプロジェクトごとにパスが異なるが、ここでは Vite を使って Vue アプリケーションのスキャフォールドをしているので、 public/ が公開用ディレクトリとなる。

ワーカーとモックの紐付け

handler.ts と同じディレクトリに browser.ts を作成し、 setupWorker 関数を用いて、ワーカーとモックハンドラを紐付ける。

src/mocks/browser.ts
import { setupWorker } from 'msw'
import { handlers } from './handlers'

export const worker = setupWorker(...handlers)

ワーカーを動かす

ワーカーの準備が整ったので、アプリケーション側のコードでワーカーを開始する

src/App.vue
<template>
  <div>Hello, MSW!!</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'App',
  setup() {
    if (process.env.NODE_ENV === 'development') {
      import('./mocks/browser').then(module => {
        module.worker.start()
      })
    }
  }
})
</script>

コンソールに以下のメッセージが出れば成功

[MSW] Mocking enabled.

動作確認

App.vue を修正し、ワーカーが立ち上がったら axios/users を呼び出し、レスポンスを state に保存し、それをテンプレートで描画できるようにする。

src/App.vue
<template>
  <div>
    <ul>
      <li :key="user.id" v-for="user in state.users">
        <p>id: {{ user.id }}</p>
        <p>name: {{ user.name }}</p>
      </li>
    </ul>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive } from 'vue'
import axios from 'axios'
type User = { id: number; name: string }

export default defineComponent({
  name: 'App',
  setup() {
    const state = reactive({
      users: [] as User[]
    })

    if (process.env.NODE_ENV === 'development') {
      import('./mocks/browser').then(async module => {
        await module.worker.start()
        const response = await axios.get('/users')
        state.users = response.data.users
      })
    }

    return { state }
  }
})
</script>

モックされたユーザー一覧が描画されることが確認できた

このスクラップは1ヶ月前にクローズされました
ログインするとコメントできます