Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
19
Help us understand the problem. What are the problem?

posted at

updated at

Organization

axios をモックする方法 (React + TypeScript)

はじめに

HTTPクライアントでお馴染みの axios のモック化を試したかったので、
それに関しての導入記事となります。

モックに関しては、 axios-mock-server を利用します。

フロントは、 React + TypeScript でサンプルを記述します。

環境

  • macOS Catalina 10.15.6
  • node: v15.3.0
  • yarn: 1.22.10
  • TypeScript: 4.1.2
  • React: 17.0.0
  • axios-mock-server: 0.19.0

1. パッケージの導入

$ yarn add axios
$ yarn add --dev axios-mock-server

npm じゃなくて yarn を利用しています。

2. axios を利用した HTTPクライアント の作成

axios を利用した形の HTTPクライアント部分を実装します。
とりあえず最低限の get/post のみです。

src/data/rest.ts
import axios from "axios";

type Data = { [key: string]: string | number | boolean | object }

const rest = (() => {
  const client = axios.create({
    baseURL: '', // 今回は未指定 (通常は env などから参照させる)
    timeout: 15000,
  });
  return {
    client,
    get: <T = any, R = AxiosResponse<T>>(url: string): Promise<R> => {
      return client.get(url);
    },
    post: <T = any, R = AxiosResponse<T>>(url: string, data: Data): Promise<R> => {
      return client.post(url, data);
    }
})();

export { rest };

この時点ではまだモックを考慮していません。
また、本サンプルでは POST は未使用ですが一応定義しておきます。

3. API のインターフェースを定義

今回仮に User一覧 を返すAPIを想定します。
一旦クエリパラメータは無しで。

Method URL
GET http://localhost:3000/user/list

レスポンスの型定義

src/data/type/index.ts
type User = {
  id: number;
  name: string;
}

export type { User };

APIの実装部分

src/data/api/getUsers.ts
import { rest } from '../rest';
import { User } from '../type';

const getUsers = async (): Promise<User[]> => {
  const url = "/user/list";
  try {
    const { data } = await rest.get<User[]>(url)
    return data;
  } catch (error) {
    throw new Error(error);
  }
}

export { getUsers };

コンポーネント側から呼び出す場合はこんな感じです。

src/component/Users.tsx
import React, { useEffect } from 'react';
import { getUsers } from '../data';

const Users: React.FC = () => {
  useEffect(() => {
    getUsers().then((users) => {
      console.log('# users', users);
    });
  }, []);
  return <span>Users</span>;
};

export { Users };

4. mockserverrc の作成

プロジェクトのルート階層(package.jsonがある場所)に .mockserverrc を作成します。
今回 モックAPI のファイルとして、
/src/data/mock に格納したいので、そこのパスを指定しています。

.mockserverrc
{
  "input": "./src/data/mock"
}

5. モックAPI の作成

モックAPIを格納するディレクトリは以下の通りです。
(見ての通りディレクトリ構造に沿って、自動的にルーティングが設定されます)

├── data
│   └── mock
│       ├── $mock.ts  ... ※自動生成されるファイル (後述で説明)
│       └── user
│           └── list.ts

User一覧のモックAPIの実装です。

src/data/mock/user/list.ts
import { MockMethods, MockResponse } from 'axios-mock-server';
import { User } from '../../type';

const list: MockMethods = {
  get: async (): Promise<MockResponse> => {
    const data: User[] = [
      {
        id: 1,
        name: 'A'
      },
      {
        id: 2,
        name: 'B'
      }
    ];
    return [200, data]; // 200 はステータスコード
  }
};

export default list; // ここは `default export` にしないと動かない

6. モックAPIをビルドするスクリプトを定義

package.json の scripts にモックAPIのビルド設定を追記します。
-c で 設定ファイルを指定しています。

package.json
  ...
  "scripts": {
    ...
    "mock:build": "axios-mock-server -c .mockserverrc"
  },

7. モックAPIのビルド

以下のコマンドを実行します。

$ yarn mock:build

$mock.ts が自動生成されていればOKです。
生成されたコードは以下の通りです。
自動生成されたファイルは、適宜.gitignoreに追加してください。

data/mock/$mock.ts
/* eslint-disable */
import { AxiosInstance } from 'axios'
import mockServer from 'axios-mock-server'
import mock0 from './user/list'

export default (client?: AxiosInstance) => mockServer([
  {
    path: '/user/list',
    methods: mock0
  }
], client, '')

8. axios とモックの紐付け

手順 2. で生成した HTTPクライアント に修正を加えます。
自動生成した mock モジュールを import し、
関数呼び出しの引数に axios の client を渡しております。

また、お好みで ログ出力 や 遅延設定 は行なえます。

src/data/rest.ts
import axios, { AxiosResponse } from "axios";
+ import { mock } from './mock';

  ... 省略 ...

+ const useMock = true;
+ if (useMock) {
+   mock(rest.client)
+     .enableLog()
+     .setDelayTime(500);
+ }

export { rest };

9. 起動コマンドの追加 及び 動作確認

このままだとモックAPIを改修する度に、
mock:buildコマンドを実行しないといけないので、
独自の起動コマンドを追加します。

package.json の scripts に以下を追加します。

package.json
  ...
  "scripts": {
    ...
    "mock:build": "axios-mock-server -c .mockserverrc"
+   "mock:start": "axios-mock-server -c .mockserverrc && react-scripts start"
  },

react-scripts startyarn start で実行するコマンド内容です。

ローカルでの実行は以下のコマンドとなります。

$ yarn mock:start

enableLog()を有効にしていると、API呼び出し時にログが出力されます。
スクリーンショット 2020-12-04 16.51.51.png

まとめ

以上、axios をモックする方法となります。
サンプルコードは以下にアップしています。
https://github.com/unpii/react-axios-mock-example

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
19
Help us understand the problem. What are the problem?