axios-mock-adapter vs fetch-mock vs mockttp vs nock
HTTPリクエストモックライブラリ
axios-mock-adapterfetch-mockmockttpnock類似パッケージ:

HTTPリクエストモックライブラリ

これらのライブラリは、HTTPリクエストをモックするためのツールであり、テスト環境でのAPI呼び出しのシミュレーションを可能にします。これにより、外部サービスに依存せずにアプリケーションの動作を検証でき、ユニットテストや統合テストの効率を向上させます。モックを使用することで、ネットワークの遅延やエラーを再現し、さまざまなシナリオをテストすることができます。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
axios-mock-adapter2,055,6793,55167.9 kB961年前MIT
fetch-mock1,176,6601,309157 kB64ヶ月前MIT
mockttp336,9928501.84 MB404ヶ月前Apache-2.0
nock013,081185 kB8317日前MIT

機能比較: axios-mock-adapter vs fetch-mock vs mockttp vs nock

モックの簡易性

  • axios-mock-adapter:

    Axiosのインスタンスに直接統合されており、簡単にモックを設定できます。特定のリクエストに対してレスポンスを指定するのが容易で、テストが迅速に行えます。

  • fetch-mock:

    Fetch APIに特化しており、シンプルなAPIでモックを設定できます。リクエストのURLやメソッドに基づいてレスポンスを簡単に指定でき、直感的に使用できます。

  • mockttp:

    HTTPサーバーをモックするための強力な機能を提供しており、複雑なリクエストやレスポンスのシナリオを簡単に設定できます。リクエストの遅延やエラーをシミュレートすることも可能です。

  • nock:

    Node.jsのHTTPリクエストをモックするために設計されており、リクエストのインターセプトが容易です。特定のリクエストに対してカスタマイズされたレスポンスを設定でき、非常に柔軟です。

テストの柔軟性

  • axios-mock-adapter:

    Axiosの特性を活かし、さまざまなリクエストに対して異なるレスポンスを設定できます。ユニットテストや統合テストでの柔軟性が高いです。

  • fetch-mock:

    Fetch APIの特性を利用し、リクエストのメソッドやヘッダーに基づいて異なるレスポンスを返すことができます。多様なテストシナリオに対応可能です。

  • mockttp:

    HTTPサーバーの動作を模倣できるため、複雑なシナリオやエラー処理のテストが容易です。多様なリクエストパターンに対応できます。

  • nock:

    Node.jsのHTTPリクエストをモックするため、リクエストの詳細な制御が可能です。特定の条件に基づいてレスポンスを変更することができ、柔軟なテストが可能です。

エラーハンドリングのサポート

  • axios-mock-adapter:

    エラーレスポンスを簡単に設定でき、APIのエラーハンドリングをテストするのに便利です。特定のエラーコードやメッセージを返すことができます。

  • fetch-mock:

    Fetch APIのエラーレスポンスをモックすることができ、ネットワークエラーやサーバーエラーをシミュレートできます。

  • mockttp:

    HTTPサーバーのエラーレスポンスを簡単に設定でき、エラーハンドリングのテストが容易です。リクエストの失敗をシミュレートすることができます。

  • nock:

    特定のリクエストに対してエラーレスポンスを返すことができ、エラーハンドリングのテストを簡単に行えます。

パフォーマンス

  • axios-mock-adapter:

    Axiosのモックは軽量で、テストのパフォーマンスに影響を与えません。迅速なレスポンスを提供し、テストの実行時間を短縮します。

  • fetch-mock:

    Fetch APIのモックも軽量で、テストの実行速度を向上させます。簡単に設定できるため、テストの準備時間を短縮できます。

  • mockttp:

    HTTPサーバーをモックするため、リクエストの遅延をシミュレートすることができ、パフォーマンスのテストにも適しています。

  • nock:

    Node.jsのHTTPリクエストをモックするため、パフォーマンスに優れたテストを実行できます。リクエストのインターセプトが迅速に行えるため、テストの効率が向上します。

ドキュメントとサポート

  • axios-mock-adapter:

    Axiosの公式ドキュメントに基づいており、使用方法が明確で、コミュニティのサポートも充実しています。

  • fetch-mock:

    Fetch APIに特化したドキュメントがあり、使い方が明確です。コミュニティも活発で、サポートが得やすいです。

  • mockttp:

    詳細なドキュメントがあり、複雑なシナリオの設定方法についても説明されています。サポートも充実しています。

  • nock:

    Node.jsのHTTPリクエストに特化したドキュメントがあり、使用方法が明確です。活発なコミュニティがあり、サポートも得やすいです。

選び方: axios-mock-adapter vs fetch-mock vs mockttp vs nock

  • axios-mock-adapter:

    Axiosを使用している場合、このアダプターを選択すると、Axiosのインターフェースに直接統合され、簡単にモックを作成できます。特に、Axiosの機能をフル活用したい場合に適しています。

  • fetch-mock:

    Fetch APIを使用している場合、fetch-mockを選ぶと、Fetchのインターフェースにぴったり合ったモックを提供します。Fetch APIの特性を活かしたい場合に最適です。

  • mockttp:

    mockttpは、HTTPサーバーをモックするための強力なツールで、リクエストとレスポンスの詳細な制御が可能です。複雑なシナリオをテストしたい場合や、サーバーの動作を模倣したい場合に適しています。

  • nock:

    nockは、Node.jsのHTTPリクエストをモックするためのライブラリで、リクエストのインターセプトとレスポンスのカスタマイズが容易です。特に、Node.jsアプリケーションのテストに特化しているため、サーバーとの通信を模擬したい場合に最適です。

axios-mock-adapter のREADME

axios-mock-adapter

Axios adapter that allows to easily mock requests

Installation

Using npm:

$ npm install axios-mock-adapter --save-dev

It's also available as a UMD build:

axios-mock-adapter works on Node as well as in a browser, it works with axios v0.17.0 and above.

Example

Mocking a GET request

const axios = require("axios");
const AxiosMockAdapter = require("axios-mock-adapter");

// This sets the mock adapter on the default instance
const mock = new AxiosMockAdapter(axios);

// Mock any GET request to /users
// arguments for reply are (status, data, headers)
mock.onGet("/users").reply(200, {
  users: [{ id: 1, name: "John Smith" }],
});

axios.get("/users").then(function (response) {
  console.log(response.data);
});

Mocking a GET request with specific parameters

const axios = require("axios");
const AxiosMockAdapter = require("axios-mock-adapter");

// This sets the mock adapter on the default instance
const mock = new AxiosMockAdapter(axios);

// Mock GET request to /users when param `searchText` is 'John'
// arguments for reply are (status, data, headers)
mock.onGet("/users", { params: { searchText: "John" } }).reply(200, {
  users: [{ id: 1, name: "John Smith" }],
});

axios
  .get("/users", { params: { searchText: "John" } })
  .then(function (response) {
    console.log(response.data);
  });

When using params, you must match all key/value pairs passed to that option.

To add a delay to responses, specify a delay amount (in milliseconds) when instantiating the adapter

// All requests using this instance will have a 2 seconds delay:
const mock = new AxiosMockAdapter(axiosInstance, { delayResponse: 2000 });

You can restore the original adapter (which will remove the mocking behavior)

mock.restore();

You can also reset the registered mock handlers with resetHandlers

mock.resetHandlers();

You can reset both registered mock handlers and history items with reset

mock.reset();

reset is different from restore in that restore removes the mocking from the axios instance completely, whereas reset only removes all mock handlers that were added with onGet, onPost, etc. but leaves the mocking in place.

Mock a low level network error

// Returns a failed promise with Error('Network Error');
mock.onGet("/users").networkError();

// networkErrorOnce can be used to mock a network error only once
mock.onGet("/users").networkErrorOnce();

Mock a network timeout

// Returns a failed promise with Error with code set to 'ECONNABORTED'
mock.onGet("/users").timeout();

// timeoutOnce can be used to mock a timeout only once
mock.onGet("/users").timeoutOnce();

Passing a function to reply

mock.onGet("/users").reply(function (config) {
  // `config` is the axios config and contains things like the url

  // return an array in the form of [status, data, headers]
  return [
    200,
    {
      users: [{ id: 1, name: "John Smith" }],
    },
  ];
});

Passing a function to reply that returns an axios request, essentially mocking a redirect

mock.onPost("/foo").reply(function (config) {
  return axios.get("/bar");
});

Using a regex

mock.onGet(/\/users\/\d+/).reply(function (config) {
  // the actual id can be grabbed from config.url

  return [200, {}];
});

Using variables in regex

const usersUri = "/users";
const url = new RegExp(`${usersUri}/*`);

mock.onGet(url).reply(200, users);

Specify no path to match by verb alone

// Reject all POST requests with HTTP 500
mock.onPost().reply(500);

Chaining is also supported

mock.onGet("/users").reply(200, users).onGet("/posts").reply(200, posts);

.replyOnce() can be used to let the mock only reply once

mock
  .onGet("/users")
  .replyOnce(200, users) // After the first request to /users, this handler is removed
  .onGet("/users")
  .replyOnce(500); // The second request to /users will have status code 500
// Any following request would return a 404 since there are
// no matching handlers left

Mocking any request to a given url

// mocks GET, POST, ... requests to /foo
mock.onAny("/foo").reply(200);

.onAny can be useful when you want to test for a specific order of requests

// Expected order of requests:
const responses = [
  ["GET", "/foo", 200, { foo: "bar" }],
  ["POST", "/bar", 200],
  ["PUT", "/baz", 200],
];

// Match ALL requests
mock.onAny().reply((config) => {
  const [method, url, ...response] = responses.shift();
  if (config.url === url && config.method.toUpperCase() === method)
    return response;
  // Unexpected request, error out
  return [500, {}];
});

Requests that do not map to a mock handler are rejected with a HTTP 404 response. Since handlers are matched in order, a final onAny() can be used to change the default behaviour

// Mock GET requests to /foo, reject all others with HTTP 500
mock.onGet("/foo").reply(200).onAny().reply(500);

Mocking a request with a specific request body/data

mock.onPut("/product", { id: 4, name: "foo" }).reply(204);

Using an asymmetric matcher, for example Jest matchers

mock
  .onPost(
    "/product",
    { id: 1 },
    {
      headers: expect.objectContaining({
        Authorization: expect.stringMatching(/^Basic /),
      })
    }
  )
  .reply(204);

Using a custom asymmetric matcher (any object that has a asymmetricMatch property)

mock
  .onPost("/product", {
    asymmetricMatch: function (actual) {
      return ["computer", "phone"].includes(actual["type"]);
    },
  })
  .reply(204);

.passThrough() forwards the matched request over network

// Mock POST requests to /api with HTTP 201, but forward
// GET requests to server
mock
  .onPost(/^\/api/)
  .reply(201)
  .onGet(/^\/api/)
  .passThrough();

Recall that the order of handlers is significant

// Mock specific requests, but let unmatched ones through
mock
  .onGet("/foo")
  .reply(200)
  .onPut("/bar", { xyz: "abc" })
  .reply(204)
  .onAny()
  .passThrough();

Note that passThrough requests are not subject to delaying by delayResponse.

If you set onNoMatch option to passthrough all requests would be forwarded over network by default

// Mock all requests to /foo with HTTP 200, but forward
// any others requests to server
const mock = new AxiosMockAdapter(axiosInstance, { onNoMatch: "passthrough" });

mock.onAny("/foo").reply(200);

Using onNoMatch option with throwException to throw an exception when a request is made without match any handler. It's helpful to debug your test mocks.

const mock = new AxiosMockAdapter(axiosInstance, { onNoMatch: "throwException" });

mock.onAny("/foo").reply(200);

axios.get("/unexistent-path");

// Exception message on console:
//
// Could not find mock for: 
// {
//   "method": "get",
//   "url": "http://localhost/unexistent-path"
// }

As of 1.7.0, reply function may return a Promise:

mock.onGet("/product").reply(function (config) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      if (Math.random() > 0.1) {
        resolve([200, { id: 4, name: "foo" }]);
      } else {
        // reject() reason will be passed as-is.
        // Use HTTP error status code to simulate server failure.
        resolve([500, { success: false }]);
      }
    }, 1000);
  });
});

Composing from multiple sources with Promises:

const normalAxios = axios.create();
const mockAxios = axios.create();
const mock = new AxiosMockAdapter(mockAxios);

mock
  .onGet("/orders")
  .reply(() =>
    Promise.all([
      normalAxios.get("/api/v1/orders").then((resp) => resp.data),
      normalAxios.get("/api/v2/orders").then((resp) => resp.data),
      { id: "-1", content: "extra row 1" },
      { id: "-2", content: "extra row 2" },
    ]).then((sources) => [
      200,
      sources.reduce((agg, source) => agg.concat(source)),
    ])
  );

History

The history property allows you to enumerate existing axios request objects. The property is an object of verb keys referencing arrays of request objects.

This is useful for testing.

describe("Feature", () => {
  it("requests an endpoint", (done) => {
    const mock = new AxiosMockAdapter(axios);
    mock.onPost("/endpoint").replyOnce(200);

    feature
      .request()
      .then(() => {
        expect(mock.history.post.length).toBe(1);
        expect(mock.history.post[0].data).toBe(JSON.stringify({ foo: "bar" }));
      })
      .then(done)
      .catch(done.fail);
  });
});

You can clear the history with resetHistory

mock.resetHistory();