はじめに
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 のみです。
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 |
レスポンスの型定義
type User = {
id: number;
name: string;
}
export type { User };
APIの実装部分
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 };
コンポーネント側から呼び出す場合はこんな感じです。
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
に格納したいので、そこのパスを指定しています。
{
"input": "./src/data/mock"
}
5. モックAPI の作成
モックAPIを格納するディレクトリは以下の通りです。
(見ての通りディレクトリ構造に沿って、自動的にルーティングが設定されます)
├── data
│ └── mock
│ ├── $mock.ts ... ※自動生成されるファイル (後述で説明)
│ └── user
│ └── list.ts
User一覧のモックAPIの実装です。
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
で 設定ファイルを指定しています。
...
"scripts": {
...
"mock:build": "axios-mock-server -c .mockserverrc"
},
7. モックAPIのビルド
以下のコマンドを実行します。
$ yarn mock:build
$mock.ts
が自動生成されていればOKです。
生成されたコードは以下の通りです。
自動生成されたファイルは、適宜.gitignore
に追加してください。
/* 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 を渡しております。
また、お好みで ログ出力 や 遅延設定 は行なえます。
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
に以下を追加します。
...
"scripts": {
...
"mock:build": "axios-mock-server -c .mockserverrc"
+ "mock:start": "axios-mock-server -c .mockserverrc && react-scripts start"
},
react-scripts start
は yarn start
で実行するコマンド内容です。
ローカルでの実行は以下のコマンドとなります。
$ yarn mock:start
enableLog()
を有効にしていると、API呼び出し時にログが出力されます。
まとめ
以上、axios をモックする方法となります。
サンプルコードは以下にアップしています。
https://github.com/unpii/react-axios-mock-example