MirageJSとVue.jsを使用したAPIモックの設定
公開: 2022-03-10SPAとJAMstackの時代には、APIとフロントエンド開発の間で常に関心の分離がありました。 野生で発見される可能性のあるほとんどすべてのJavaScriptプロジェクトは、WebサービスまたはAPIと対話し、認証またはユーザー関連データの取得に使用します。
したがって、プロジェクトに取り組んでいて、必要なAPIがまだバックエンドチームによって実装されていない場合、または機能をすばやくテストする必要がある場合は、次のオプションがいくつかあります。
- 実際のバックエンドのローカルで実行されているバージョンにプロキシすることができますが、ほとんどの場合、フロントエンド開発者としてはプロキシできません。
- 実際のリクエストをコメントアウトして、モックデータに置き換えることができます。 (これは問題ありませんが、本番環境に移行するために元に戻す必要があり、ネットワークの状態と遅延を処理できない可能性があるため、それほど優れていません。)
APIモックとは何ですか?
APIモックは、実際のAPIの模倣またはシミュレーションです。 これは主に、実際のバックエンドAPIに対して行われるはずのリクエストをインターセプトするために行われますが、このモックはフロントエンドに存在します。
APIモックが重要な理由
APIモックは、多くの点で非常に重要です。
- 機能を構築する前に本番APIに依存しない、非常に優れたフロントエンド開発エクスペリエンスを実現します。
- フロントエンド全体を共有することができ、実際のバックエンドAPIに依存せずに機能します。
Mirage JSとは何ですか?
Mirage JSは5年前に作成され、Sam Selikoffが2020年1月24日にTwitterで正式にリリースを発表する前に、Emberコミュニティでほとんど使用されていました。
Mirage JSは、バックエンドAPIに依存せずにバックエンドAPIをテストする際の問題点を解決します。 本番APIをモックすることで、シームレスなフロントエンド開発エクスペリエンスを実現します。
Mirage JSは、Vue.js、React、Angular、Emberフレームワーク用のAPIモックライブラリです。
Mirage JSをより良い選択にする理由は何ですか?
APIモックには他のオプション(Axiosインターセプター、TypicodeのJSONサーバーなど)がありますが、Mirageについて非常に興味深いと思うのは、開発プロセスの邪魔にならないことです(ご覧のとおり)。少しVueで設定したとき)。 軽量でありながらパワフルです。
バッテリーが付属しており、タイミングオプションを使用して低速ネットワークをシミュレートするなど、実際の本番API消費シナリオを再現できます。
MirageJSとVue.jsの使用を開始する
Mirage JSとは何か、そしてそれがフロントエンド開発ワークフローにとって重要である理由がわかったところで、プログレッシブWebフレームワークであるVue.jsを使用してセットアップする方法を見てみましょう。
グリーンフィールド(クリーンインストール)Vueプロジェクトの作成
Vue CLIを使用して、プロジェクトを作成して実行するディレクトリ(ターミナルで)に移動して、新しいVue.jsプロジェクトを作成します。
vue create miragejs-demo-vue
上記のコマンドは、新しいVueプロジェクトをセットアップします。これで、 yarn serve
またはnpm run serve
のいずれかにcd
して実行できます。
#MirageJSのインストール
次に、次のコマンドを実行して、 Vue.jsプロジェクトに開発依存関係としてMirageJSをインストールしましょう。
yarn add -D miragejs
または、NPMを使用している場合は、次のコマンドを実行します。
npm install --save-dev miragejs
以上です! MirageJSがVue.jsプロジェクトにインストールされました。
何かをモックアウトしましょう
Mirage JSをインストールしたら、Vueと通信して基本的なtodo(todoのリストを返すAPI)APIをモックアウトするように構成する方法を見てみましょう。
サーバーを定義する
開始するには、 Vue.jsプロジェクトの/src
ディレクトリにserver.jsファイルを作成する必要があります。 その後、以下を追加します。
import { Server, Model } from 'miragejs' export function makeServer({ environment = "development" } = {}) { let server = new Server({ environment, models: { todo: Model, }, seeds(server) { server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" }) }, routes() { this.namespace = "api" this.get("/todos", schema => { return schema.todos.all() }) }, }) return server }
コードの説明
まず、 server.jsファイルは、Mirage JSを設定して、定義したルートに一致するアプリで行うすべてのAPI呼び出しをインターセプトするモック(偽)サーバーの新しいインスタンスを作成する方法です。
さて、私は上記が最初は圧倒されるかもしれないことに同意しますが、ここで何が起こっているのかを詳しく見てみましょう:
import { Server, Model } from 'miragejs'
上記のコードスニペットから、 miragejs
からServer
とModel
をインポートしています。
-
Server
これは、Mirageによって公開されたクラスであり、MirageJSサーバーの新しいインスタンスをインスタンス化して偽のサーバーとして「機能」させるのに役立ちます。 -
Model
MirageのORMを利用したモデル(モデルがMirage JSデータベースエントリの構造を決定する)の作成を支援するためにMirageによって公開された別のクラス。
export function makeServer({ environment = "development" } = {}) {}
上記は基本的に、makeServerという関数をsrc/server.js
makeServer
からエクスポートします。 また、環境パラメーターを渡し、Mirageの環境モードをdevelopment
に設定していることにも注意してください(この記事の後半でテスト環境に合格することを確認します)。
makeServer
の本体
現在、 makeServer
本体でいくつかのことを行っています。 見てみましょう:
let server = new Server({})
Serverクラスの新しいインスタンスをインスタンス化し、それに構成オプションを渡します。 構成オプションの内容は、ミラージュの設定に役立ちます。
{ environment, models: { todo: Model, }, seeds(server) { server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" }) }, routes() { this.namespace = "api" this.get("/todos", schema => { return schema.todos.all() }) }, }
まず、関数定義で初期化したenvironment
パラメーターを渡します。
models: { todo: Model, },
models
オプションである次のオプションは、Mirageにモックさせたいさまざまなモデルのオブジェクトを取得します。
上記では、Modelクラスからインスタンス化するtodoモデルが必要です。
seeds(server) { server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" }) },
次のオプションは、 server
と呼ばれるパラメーターを受け取るseedsメソッドです。 seedsメソッドは、モデルのシード(シードは初期データまたはMirageのデータベースへのエントリ)を作成するのに役立ちます。 ToDoモデルのシードを作成する場合は、次のようにします。
server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" })
したがって、サーバーには、最初の引数としてモデルの名前に対応する文字列を期待するcreateメソッドがあり、次に特定のシードのプロパティまたは属性を含むオブジェクトがあります。
routes() { this.namespace = "api" this.get("/todos", schema => { return schema.todos.all() }) },
最後に、さまざまなルートを定義するroutesメソッドがあります(ルートはモックAPIエンドポイントです)MirageJSがモックします。 メソッドの本体を見てみましょう。
this.namespace = "api"
この行は、すべてのルートの名前空間を設定します。つまり、todoルートに/ api / todosからアクセスできるようになります。
this.get("/todos", schema => { return schema.todos.all() })
上記はgetルートを作成し、 this.get()
メソッドを使用してそのハンドラーを作成します。 get()
メソッドは、ルート、つまり「/ todos」と、 schema
を引数として受け取るハンドラー関数を想定しています。 スキーマオブジェクトは、MirageJSインメモリデータベースを利用したMirageのORMと対話する方法です。
ついに:
return schema.todos.all()
MirageのORMによって可能になったスキーマオブジェクトを使用して、すべてのToDoのリストを返します。
src / main.js
これでsrc/server.js
の設定は完了しましたが、Vueはそれを認識していません(少なくともまだ)。 それでは、次のようにmain.jsファイルにインポートしましょう。
import { makeServer } from "./server"
次に、次のようにmakeServer
関数を呼び出します。
if (process.env.NODE_ENV === "development") { makeServer() }
上記の条件付きのif
は、ミラージュが開発でのみ実行されるようにするためのガードです。
セットアップ完了!
これで、Vueを使用してMiragejsをセットアップしました。 実際の動作を見てみましょう。 App.vueファイルでは、コンテンツをクリアして、以下のスニペットに置き換えます。
<template> <ul> <li v-for="todo in todos" v-bind:key="todo.id">{{ todo.content }}</li> </ul> </template> <script> export default { name: 'app', data() { return { todos: [] } }, created() { fetch("/api/todos") .then(res => res.json()) .then(json => { this.todos = json.todos }) } } </script>
Vue.jsに精通している場合、上記は新しいことではありませんが、全体として、 App.vue
コンポーネントの作成時にfetch
を使用してAPIリクエストを作成し、返されたデータを渡します。コンポーネント状態のtodos配列に。 その後、v-forを使用してtodos配列を反復処理し、各todoのcontentプロパティを表示します。
ミラージュJSパートはどこにありますか?
お気づきの方もいらっしゃると思いますが、App.vueコンポーネントでは、Mirageに固有のことは何もしていません。通常どおり、API呼び出しを行っているだけです。 Mirageのこの機能は、内部でDXの原因として非常に優れています。開発中、Mirageはsrc /server.jsで定義されたルートのいずれかに一致するリクエストをインターセプトします。
ルートが本番APIエンドポイントと一致していれば、本番環境にいるときに実際の本番サーバーに切り替えるための作業は必要ないため、これは非常に便利です。
したがって、YargeServeを介してVue開発サーバーを再起動してyarn serve
をテストします。
2つのToDoのリストが表示されます。 非常に興味深いと思うことの1つは、Mirageを起動するためにターミナルコマンドを実行する必要がなかったことです。これは、Vue.jsアプリケーションの一部として実行することでオーバーヘッドがなくなるためです。
Mirage JS And Vue test-utils
すでにVueアプリケーションでVueTest-utilsを使用している場合は、Mirageを使用してネットワークリクエストをモックすることが簡単にできることを知ってワクワクするでしょう。 todosアプリケーションを使用して設定された例を見てみましょう。
ユニットテストにはJestを使用します。 したがって、フォローしている場合は、VueCLIを使用して@vue/unit-jest
プラグインを次のようにインストールできます。
vue add @vue/unit-jest
上記は、 @vue/cli-plugin-unit-jest
と@vue/test-utils
開発依存関係をインストールすると同時に、 tests
ディレクトリとjest.config.jsファイルも作成します。 また、 package.json scripts
セクションに次のコマンドを追加します(かなりきれいです)。
"test:unit": "vue-cli-service test:unit"
テストしましょう!
App.vueを次のように更新します。
<!-- src/App.vue --> <template> <div v-if="serverError" data-test> {{ serverError }} </div> <div v-else-if="todos.length === 0" data-test> No todos! </div> <div v-else> <ul> <li v-for="todo in todos" v-bind:key="todo.id" :data-test > {{ todo.content }} </li> </ul> </div> </template> <script> export default { name: "app", data() { return { todos: [], serverError: null, } }, created() { fetch("/api/todos") .then(res => res.json()) .then(json => { if (json.error) { this.serverError = json.error } else { this.todos = json.todos } }) }, } </script>
上記のスニペットでは、本当に壮大なことは何も起こっていません。 単体テストで実装するネットワークテストを可能にするように構築しているだけです。
VueCLIにはすでに/tests
フォルダーが追加されていますが、テストをテスト対象のコンポーネントの近くに配置すると、はるかに優れたエクスペリエンスになることがわかりました。 したがって、 src/
に/__tests__
フォルダーを作成し、その中にApp.spec.jsファイルを作成します。 (これは、Jestが推奨するアプローチでもあります。)
// src/__tests__/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() })
したがって、単体テストを設定するために、 @vue/test-utils
からmount
メソッドをインポートし、前に作成したMiragejsサーバーをインポートし、最後にApp.vue
コンポーネントをインポートします。
次に、 beforeEach
ライフサイクル関数を使用して、テスト環境に合格しながらMirageJSサーバーを起動します。 (デフォルトでは、環境をdevelopment
に設定していることを忘れないでください。)
最後に、 afterEach
ライフサイクルメソッドでserver.shutdown
を使用してサーバーをシャットダウンしています。
私たちのテスト
次に、テストを具体化しましょう(Mirage jsドキュメントのクイックスタートセクションを採用する予定です。したがって、 App.spec.jsは最終的に次のようになります。
// src/__tests__/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" }) }) it("shows the todos from our server", async () => { server.create("todo", { id: 1, content: "Learn Mirage JS" }) server.create("todo", { id: 2, content: "Integrate with Vue.js" }) 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-test]') await waitFor(wrapper, '[data-test]') expect(wrapper.find('[data-test]').text()).toBe("Learn Mirage JS") expect(wrapper.find('[data-test]').text()).toBe("Integrate with Vue.js") }) it("shows a message if there are no todo", async () => { // Don't create any todos const wrapper = mount(App) await waitFor(wrapper, '[data-test]') expect(wrapper.find('[data-test]').text()).toBe("No todos!") }) // 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 todoEl = wrapper.findAll(selector) if (todoEl.length > 0) { clearInterval(timer) resolve() } }, 100) }) } afterEach(() => { server.shutdown() })
注:ここではヘルパーを使用しています(Mirage JSのドキュメントで定義されています)。 テストしている要素がすでにDOMにあることを知ることができるpromiseを返します。
次に、 yarn test:unit
を実行します。
この時点で、すべてのテストに合格するはずです。
MirageJSを使用したさまざまなサーバー状態のテスト
Mirage JSサーバーを変更して、さまざまなサーバー状態をテストできます。 方法を見てみましょう。
// src/__tests__/App.spec.js import { Response } from "miragejs"
まず、MirageからResponse
クラスをインポートし、次に次のような新しいテストシナリオを作成します。
it("handles error responses from the server", async () => { // Override Mirage's route handler for /todos, just for this test server.get("/todos", () => { return new Response( 500, {}, { error: "The database is taking a break.", } ) }) const wrapper = mount(App) await waitFor(wrapper, '[data-test]') expect(wrapper.find('[data-test]').text()).toBe( "The database is taking a break." ) })
テストを実行すると、すべて合格するはずです。
結論
この記事は、Mirage JSを紹介し、それがどのようにフロントエンド開発エクスペリエンスを向上させるかを示すことを目的としています。 Mirage JSが対処するために作成した問題(実際のバックエンドAPIを使用せずに本番環境に対応したフロントエンドを構築する)と、Vue.jsを使用してセットアップする方法を確認しました。
この記事は、Mirage JSでできることの表面をかじったものですが、始めるには十分だと思います。
- ドキュメントを確認するだけでなく、MirageJSの不和サーバーに参加することもできます。
- この記事のサポートリポジトリはGitHubで入手できます。
参考文献
- ミラージュドキュメント
- MirageVueクイックスタート