1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

フロントエンド開発でMock Service WorkerをサーバサイドAPIモックとして使う

Posted at

概要

  • サーバサイドAPIはまだ実装されてないけど、Webフロントエンドの実装を進めたい
  • 顧客に見せるために作成したモックの実装を、できるだけ実際の実装に流用したい
  • E2Eテストの為だけにビジネスロジックとは関係のない実装を入れたくない
  • Mock Service Workerを使えばそんなお悩みを解決できます

Mock Service Workerとは

Service Worker APIを利用してブラウザのリクエストをインターセプトすることで、サーバサイトAPIの振る舞いを模倣するモックを構築できるフレームワークです。JSON Serverのようなモックサーバフレームワークとの違いは、単独のサーバを起動するのではなく、Service Workerを常駐してブラウザのリクエストのインターセプトすることでモック用のレスポンスを返却する仕組みになっている点です。

MDN - Service Worker API

準備

React用のサンプルが用意されているので、今回はそれを使用して挙動を見ていきたいと思います。

Mock Service Worker (以下MSW) のExamplesに記載されているインストール手順に従ってローカルに環境を構築します。

$ git clone https://github.com/mswjs/examples.git
$ cd examples
$ yarn
$ cd rest-react

$ yarn start

サービスが起動しました。
1.png
ブラウザから http:/localhost:3001 にへアクセスするとデモ画面が表示されます。
2.png

動かしてみる

usernameを入力するとログインAPIが実行されて、そのレスポンス内容が画面に表示されるというデモになります。
3.png
usernameを入力してSubmitボタンを押してみます。
4.png
ユーザー情報が画面に表示されました。この値はMSWによって実行されているログインAPIのモックから返却されたものになります。
でも せっかく入力した username が画面に表示されていません。
コードを読み進めてゆくついでに画面に username が表示されるようにしていこうと思います。

MSWの実行

デモのReactプロジェクトでは examples/rest-react/src/index.js の中でMSWを実行しています。このわずか数行の実装でブラウザからのリクエストがMSWへインターセプトされるようになります。

// Start the mocking conditionally.
if (process.env.NODE_ENV === 'development') {
  const { worker } = require('./mocks/browser')
  worker.start()
}

Reactのfetch処理

ReactではログインAPIをfetch APIでリクエストしています。ホストを指定していないので、ログインAPIは同ホスト内で実行してされている想定となっています。
JSON Serverなどを使用する場合はfetch APIに指定するホストなどを挿げ替える判定処理を施したりしますが、冒頭に記載した通りMSWではそのような必要はありません。

examples/rest-react/src/LoginForm.js

// Handle a submit event of the form
const handleFormSubmit = useCallback(
(event) => {
    // Prevent the default behavior, as we don't want
    // for our page to reload upon submit.
    event.preventDefault()

    // Perform a POST /login request and send the username
    fetch('/login', {
    method: 'POST',
    body: JSON.stringify({
        username,
    }),
    })
    .then((res) => res.json())
    // Update the state with the received response
    .then(setUserData)
},
[username],
)

MSW のコード

examples/rest-react/src/mocks 以下にMSWに関するソースコードが格納されています。
モックAPIの実態は handlers.js に実装されています。

/login というエンドポイントへpost methodでリクエストされた場合に、固定のJSONを返却するという処理になります。ちなみにこのコードには画面から入力された username を正しく取得できないバグがあるので、後ほど修正していきたいと思います。

examples/rest-react/src/mocks/handlers.js

import { rest } from 'msw'

export const handlers = [
  rest.post('/login', (req, res, ctx) => {
    const { username } = req.body

    return res(
      ctx.json({
        id: 'f79e82e8-c34a-4dc7-a49e-9fadc0979fda',
        username,
        firstName: 'John',
        lastName: 'Maverick',
      }),
    )
  }),
]

username を画面に表示できるようにしてみる

前述の通り、ソースコードにはバグがあるので username がレスポンスでundefinedになってしまいまうため、コードを少々修正します。

examples/rest-react/src/mocks/handlers.js

Before

const { username } = req.body

After

const { username } = JSON.parse(req.body)

次に画面にレスポンスで取得した username を表示するようにしてみます。

examples/rest-react/src/LoginForm.js

Before

  if (userData) {
    return (
      <div>
        <h1>
          <span data-testid="firstName">{userData.firstName}</span>{' '}
          <span data-testid="lastName">{userData.lastName}</span>
        </h1>
        <p data-testid="userId">{userData.id}</p>
      </div>
    )
  }

After

  if (userData) {
    return (
      <div>
        <h1>
          <span data-testid="firstName">{userData.firstName}</span>{' '}
          <span data-testid="lastName">{userData.lastName}</span>
        </h1>
        {/** 入力した username を表示してみる */}
        <p data-testid="username" style={{ color: 'red' }}>
          {userData.username}
        </p>
        <p data-testid="userId">{userData.id}</p>
      </div>
    )
  }

実行してみる

usernameを入力してSubmitボタンを押してみます。
3.png
ログイン後の画面に入力した username が赤文字で表示されました。
5.png

最後に

今回はMSWのデモを利用して簡単な仕組みを見ていきました。MSWを使用することでクライアントアプリケーションのコードに変更を加えることなくサーバサイドのモックと連携できることがわかりました。
次回は同デモを使ってE2Eテストの実装を見ていきたいと思います。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?