Skip to main content

JavaScriptでモックAPIサーバーを作成する方法

著者

David Ekete

feature mock api js

2022年10月20日

0 分で読めます

フロントエンド機能の開発やテストは、依存するバックエンドがまだ準備できていない場合、特に難しくなることがあります。バックエンドAPIへの依存によって、開発プロセスが遅れることも少なくありません。

このような状況では、モックAPIを作成することで、バックエンドとは独立して機能を開発できるため、多くの時間を節約できます。また、APIの準備が整う前に、テストを容易に行い、APIが失敗する可能性のあるシナリオを特定できます。

この記事では、モックAPIサーバーの概要、モックAPIの作成に使えるツール、開発やテストを効率化する方法、簡単なモックサーバーのセットアップ方法を解説します。

モックAPIサーバーとは

モックAPIサーバーとは、クライアントから受け取ったリクエストに対して、現実的なレスポンスを返す模擬APIサーバーです。通常、開発中のバックエンドサーバーの代わりとして使われます。

モックAPIサーバーは、現実的なレスポンス値を含む仮データを使って実際のAPIを模倣しますが、データの永続化など、元のコンポーネントが持つ機能面・非機能面の特性の多くは備えていません。

モックAPIサーバーは、次のようなさまざまな場面で使用できます。

  • 開発:モックAPIサーバーを使うと、フロントエンドチームとバックエンドチームの依存関係を一時的に解消できます。それぞれのチームが独立して作業、開発、テストを進められます。

  • テスト:ソフトウェア開発に欠かせないテストを、フロントエンドチームがバックエンドチームによる完全なAPIの開発を待たずに実施できます。また、すべてのテストリクエストが実際のAPIではなくモックAPIサーバーに送られるため、実際のAPIがテストデータで汚染されることも防げます。

  • 外部コンポーネント:Storybookなどのツールを使ってフロントエンド機能を紹介する際、モックAPIサーバーを使って外部依存関係を模擬することもできます。

モックAPIのベストプラクティス

モックAPIサーバーを作成するときは、次のベストプラクティスを念頭に置きましょう。

  • モックAPIは、実際のAPIと同じスキーマとインターフェースに対応している必要があります。これにより、レスポンスをより現実的なものにできます。

  • アプリケーションに外部依存関係がある場合は、モックAPIでもそれらを模擬する必要があります。

  • モックAPIは、リクエストの転送に対応している必要があります。これにより、実際のAPIが開発された後、モックレスポンスから実際のレスポンスへ段階的に切り替えられます。

  • モックAPIでは、予期しないエラーやパフォーマンスの低下、無効なユーザー入力をシミュレートできるようにします。こうすることで、アプリケーションがこれらの状況に適切に対応できるようになります。

APIモックツール

モックAPIサーバーの作成に役立つツールは数多くあります。たとえば、次のようなものがあります。

  • Mock Service Worker (MSW):Mock Service Workerは、Service Worker APIを利用するAPIモックライブラリです。このAPIにより、MSWはプロキシサーバーとして実際のリクエストをインターセプトし、モックレスポンスを返せます。リクエストのインターセプトはネットワークレベルで行われるため、アプリケーションはレスポンスがモックAPIから返されていることを認識しません。

  • Postman:Postmanは、APIの構築、使用、テスト、ドキュメント作成を行うためのプラットフォームです。保存済みのモックデータを返すモックAPIサーバーも作成できます。Postmanはリクエストの設定を保存済みのサンプルと照合し、設定に最も近いデータを含むモックレスポンスを返します。操作しやすいGUIを備えているため、Postmanのモックサーバーを簡単にセットアップできます。

  • Mirage JS:Mirage JSは、バックエンドサービスに依存せずにJavaScriptアプリケーションを構築・テストできるAPIモックライブラリです。動的なシナリオを簡単に作成できるため、モックAPIをより現実的なものにできます。動的なシナリオを作成でき、インメモリデータベースも備えているMirage JSは、モックAPIサーバーを作成するうえで最も柔軟な選択肢です。

Mirage JSでモックAPIサーバーを作成する

このセクションでは、Mirage JSを使って簡単なモックAPIサーバーを作成する方法を説明します。

前提条件

始める前に、次のものを用意してください。

  • システムにNode.js v16以降がインストールされていること。

  • 任意のIDE。

  • React.jsの基本的な知識。

エディターで手順を進めるには、チュートリアルのGitHubリポジトリをクローンしてください。

モックサーバーをセットアップする

ターミナルで次のコマンドを実行し、必要な依存関係をインストールして開発サーバーを起動します。

npm install
npm run start

ウィジェットが回転するだけで、アプリには機能が表示されないはずです。これは、準備ができていないAPIからアプリがデータを取得しようとしているためです。開発プロセスを効率化するため、モックサーバーを作成しましょう。

ティール色の背景に青い円形のスピナーが表示されたReactアプリの読み込み画面

srcディレクトリにmock.jsというファイルを作成し、次のコードを追加します。

//mock.js
import { createServer } from "miragejs";

const createMockServer = function () {
 let server = createServer();

 return server;
};

export default createMockServer;

上記のコードでは、miragejsからcreateServerをインポートしています。この関数は、指定した設定オブジェクトを使ってMirageサーバーを起動します。設定オブジェクトには、サーバーが処理する各種ルート、モック用のインメモリデータベース、名前空間などの情報を含めることができます。

createMockServer関数は、サーバーのインスタンスを作成して返します。

インメモリのモックデータベースを作成する

次に、Mirageのデータレイヤーを使って簡単なモックデータベースを作成し、データを保存・返却できるようにします。

mock.jsファイルを次のコードに合わせて更新します。

//mock.js
import { createServer, Model } from "miragejs";

const createMockServer = function () {
 let server = createServer({
   models: {
     todos: Model
   },
 });

 return server;
};

export default createMockServer;

修正後のコードでは、miragejsからModelもインポートしています。これはMirageモデルの基本定義です。

次に、引数として設定オブジェクトをcreateServerに渡しました。設定オブジェクト内では、modelsプロパティにオブジェクトを設定し、そのオブジェクト内でmodelsプロパティのtodosにmodelを設定しています。これにより、Mirageはインメモリデータベースに空のtodosコレクションを作成します。

インメモリデータベースにデータを登録する

次に、seedsフックを使ってインメモリデータベースにデータを手動で追加します。seedsフックを使うと、Mirageに初期データを設定できるため、アプリケーションの初回起動時からモックAPIに表示用のデータを用意できます。

データベースに初期データを登録するには、createServerの設定オブジェクト内でmodelsプロパティの下に次のコードを追加します。

    //mock.js
   seeds(server) {
    server.create("todo", {
      id: 1,
      title: "Reach out to a friend",
      completed: true,
    });

    server.create("todo", {
      id: 2,
      title: "Make breakfast",
      completed: true,
    });

    server.create("todo", {
      id: 3,
      title: "Text John Doe",
      completed: false,
    });
  },

上記のコードでは、設定オブジェクトにseedsフックを追加しました。seedsフックは、引数としてサーバーのインスタンスを受け取ります。

次に、サーバーインスタンスでcreateメソッドを呼び出し、インメモリデータベースにデータを追加しました。createメソッドは2つの引数を受け取ります。1つ目はデータを保存するコレクションの単数形の名前(例:「todos」は「todo」)、2つ目は保存するデータです。

モックルートハンドラーを定義する

次に、routesフックを使ってルートハンドラーを定義します。routesフックでは、利用可能な各パスとHTTPリクエストに対するルートハンドラーを指定できます。

API呼び出しのルートハンドラーを追加するには、createServerの設定オブジェクトでseedsフックの直下に次のコードを追加します。

routes() {
    this.namespace = "api/todos";

    this.get("/", (schema, request) => {
      return schema.todos.all().models
    });
  },

上記のコードでは、routesフックを使ってすべてのルートハンドラーに共通の名前空間(api/todos)を定義しています。これにより、各ルートハンドラーで繰り返し指定する必要がなくなります。

次に、パスとコールバックを受け取るgetメソッドを使ってGETルートハンドラーを定義しました。コールバックでは、アプリからschema引数にアクセスできます。これを使ってインメモリデータベースにアクセスします。また、リクエストボディにアクセスするためのrequest引数も利用できます。

最後に、schema.todosでallメソッドを呼び出し、インメモリデータベース内のすべてのtodoを返しました。schema引数にモデル名を連結すると、インメモリモデルにアクセスできます。allメソッドは、modelNameとmodelsの2つのプロパティを持つCollectionオブジェクトを返します。

modelNameプロパティはモデル名、modelsプロパティは登録済みデータを含む配列です。

次のコードをroutesフックに追加して、POSTルートハンドラーを定義します。

  this.post("/new", (schema, request) => {
       let attrs = JSON.parse(request.requestBody);
       attrs.completed = false;

       return schema.todos.create(attrs);
   });

上記のコールバック関数では、リクエストオブジェクトからリクエストボディを取得して解析します。新しいタスクはデフォルトで未完了にするため、completedプロパティをfalseに設定します。Mirageは、インメモリデータベースに最初に登録された最後のtodoのidをインクリメントして、新しいtodoに一意のidを自動で割り当てます。最後に、`create``メソッドを使って新しいtodoをデータベースに追加しました。

次のコードをroutesフックに追加して、PATCHルートハンドラーを定義します。

   this.patch("/:id", (schema, request) => {
       let newAttrs = JSON.parse(request.requestBody);
       let { id } = request.params;
       let todo = schema.todos.find(id);
       return todo.update(newAttrs);
   });

上記のコールバック関数では、リクエストオブジェクトからリクエストボディを取得して解析します。次に、リクエストボディに付属するparamsオブジェクトからidプロパティを分割代入します。findメソッドを使って、インメモリデータベースから一致するidを持つtodoを検索します。最後に、updateメソッドを使ってtodoを更新します。

次のコードをroutesフックに追加して、DELETEルートハンドラーを定義します。

  this.delete("/:id", (schema, request) => {
       let { id } = request.params;
       return schema.todos.find(id).destroy();
   });

この関数では、リクエストボディに付属するparamsオブジェクトからidプロパティを分割代入します。次に、findメソッドを使ってインメモリデータベースから一致するidを持つtodoを検索し、destroyメソッドを呼び出してインメモリデータベースから削除しました。

完成したモックサーバーは次のようになります。

import { createServer, Model } from "miragejs";

const createMockServer = function () {
 let server = createServer({
   models: {
     todos: Model,
   },

   seeds(server) {
     server.create("todo", {
       id: 1,
       title: "Reach out to a friend",
       completed: true,
     });

     server.create("todo", {
       id: 2,
       title: "Make breakfast",
       completed: true,
     });

     server.create("todo", {
       id: 3,
       title: "Text John Doe",
       completed: false,
     });
   },

   routes() {
     this.namespace = "api/todos";

     this.get("/", (schema, request) => {
       return schema.todos.all().models;
     });

     this.post("/new", (schema, request) => {
       let attrs = JSON.parse(request.requestBody);
       attrs.completed = false;

       return schema.todos.create(attrs);
     });

     this.patch("/:id", (schema, request) => {
       let newAttrs = JSON.parse(request.requestBody);
       let id = request.params.id;
       let todo = schema.todos.find(id);
       return todo.update(newAttrs);
     });

     this.delete("/:id", (schema, request) => {
       let id = request.params.id;
       return schema.todos.find(id).destroy();
     });
   },
 });

 return server;
};

export default createMockServer;

最後に、createMockServer関数をApp.jsファイルにインポートし、App.jsファイル内でcreateMockServer関数を呼び出してモックサーバーを起動します。

たとえば、次のようにします。

//app.js
import createMockServer from "./mock";

createMockServer();

Reactアプリケーションを開くと、モックAPIに登録したデータがToDoアプリに表示されます。

完了済みのタスク、「Text John Doe」という未チェックのタスク、新しいToDoを入力する欄が表示されたToDoリストアプリ

これで、実際のバックエンドAPIを使う場合と同じようにToDoアプリをテストできます。

モックAPIサーバーのまとめ

この記事では、モックAPIサーバーの概要とその重要性、作成時のベストプラクティス、役立つツールについて解説しました。また、Mirage JSを使って簡単なモックAPIサーバーを作成する方法も紹介しました。

開発プロセスにモックAPIサーバーを取り入れると、開発を効率化し、独立して作業できるようになるため、ワークフローの改善につながります。

カテゴリー: