Mirageを使用したVue Test Utilsでのネットワークリクエストのモック

Vue Test Utilsを使用して、さまざまなサーバーシナリオでVueアプリケーションをテストするためにMirageサーバーを使用します。

これは、Vueアプリで既にVue Test Utilsを使用しているユーザー向けのクイックスタートガイドです。

ステップ1:Mirageのインストール

まず、Mirageがインストールされていることを確認してください。

# Using npm
npm install --save-dev miragejs

# Using Yarn
yarn add --dev miragejs

ステップ2:サーバーの定義

新しいserver.jsファイルを作成し、モックサーバーを定義します。

基本的な例を次に示します。

// src/server.js
import { createServer, Model } from "miragejs"

export function makeServer({ environment = "development" } = {}) {
  let server = createServer({
    environment,

    models: {
      user: Model,
    },

    seeds(server) {
      server.create("user", { name: "Bob" })
      server.create("user", { name: "Alice" })
    },

    routes() {
      this.namespace = "api"

      this.get("/users", (schema) => {
        return schema.users.all()
      })
    },
  })

  return server
}

Vue CLIでは、このファイルをsrc/server.jsに配置して、変更がリビルドをトリガーするようにします。

ステップ3:Mirageを使用するテストファイルの作成

これがテストするVueコンポーネントです。

<!-- src/App.vue -->
<template>
  <div v-if="serverError" data-testid="server-error">{{ serverError }}</div>

  <div v-else-if="users.length === 0" data-testid="no-users">No users!</div>

  <div v-else>
    <ul id="users">
      <li
        v-for="user in users"
        v-bind:key="user.id"
        :data-testid="'user-' + user.id"
      >
        {{ user.name }}
      </li>
    </ul>
  </div>
</template>

<script>
  export default {
    name: "app",

    data() {
      return {
        users: [],
        serverError: null,
      }
    },

    created() {
      fetch("/api/users")
        .then((res) => res.json())
        .then((json) => {
          if (json.error) {
            this.serverError = json.error
          } else {
            this.users = json.users
          }
        })
    },
  }
</script>

新しいsrc/App.spec.jsファイルを作成し、makeServer関数をインポートし、MirageをbeforeEachafterEachを使用して起動およびシャットダウンし、Mirageにtest環境を渡すようにしてください。

// src/App.spec.js
import { mount } from "@vue/test-utils"
import { makeServer } from "./server"
import App from "./App.vue"

let server

beforeEach(() => {
  server = makeServer({ environment: "test" })
})

afterEach(() => {
  server.shutdown()
})

ステップ4:Mirageサーバーを使用したテストの記述

テストを使用して、Mirageにさまざまなデータシナリオをシードし、UIの状態をアサートします。

test環境では、Mirageはデータベースseedsをロードしないため、サーバーは各テスト実行で空の状態で起動します。

it("shows the users from our server", async () => {
  server.create("user", { id: 1, name: "Luke" })
  server.create("user", { id: 2, name: "Leia" })

  const wrapper = mount(App)

  // let's wait for our vue component to finish loading data
  // we know it's done when the data-testid enters the dom.
  await waitFor(wrapper, '[data-testid="user-1"]')
  await waitFor(wrapper, '[data-testid="user-2"]')

  expect(wrapper.find('[data-testid="user-1"]').text()).toBe("Luke")
  expect(wrapper.find('[data-testid="user-2"]').text()).toBe("Leia")
})

it("shows a message if there are no users", async () => {
  // Don't create any users

  const wrapper = mount(App)
  await waitFor(wrapper, '[data-testid="no-users"]')

  expect(wrapper.find('[data-testid="no-users"]').text()).toBe("No users!")
})

// This helper method returns a promise that resolves
// once the selector enters the wrapper's dom.
const waitFor = function (wrapper, selector) {
  return new Promise((resolve) => {
    const timer = setInterval(() => {
      const userEl = wrapper.findAll(selector)
      if (userEl.length > 0) {
        clearInterval(timer)
        resolve()
      }
    }, 100)
  })
}

ステップ5:異なるサーバー状態をテストするためのMirageサーバーの変更

異なるデータシナリオに加えて、テストを使用してMirageサーバーを再構成し、新しい状況をテストできます。

たとえば、次のようにエラー状態をテストできます。

// src/App.spec.js
import { Response } from "miragejs"

it("handles error responses from the server", async () => {
  // Override Mirage's route handler for /users, just for this test
  server.get("/users", () => {
    return new Response(
      500,
      {},
      {
        error: "The database is on vacation.",
      }
    )
  })

  const wrapper = mount(App)

  await waitFor(wrapper, '[data-testid="server-error"]')

  expect(wrapper.find('[data-testid="server-error"]').text()).toBe(
    "The database is on vacation."
  )
})

beforeEachafterEachを使用してMirageを設定したため、各テストはメインサーバー定義に基づく新しいMirageサーバーを取得します。テスト内で行ったオーバーライドは、そのテストに分離されます。