「サーバが出来ていない？　俺なら3分でモックを用意できるよ。」というために。

# はじめに
フロントエンドを作っていたり他サーバと連携するバックエンドを作っていると、対向サーバが出来るまでダミーのモックサーバが欲しくなりますよね。
適当に固定のダミーデータを返すだけで良いのですが、本来の開発以外のところに工数を取られるのは嫌なものです。
探してみると色々なモックサーバがあるのですが、好みに合うものが見つからなかったので作ってみました。

**欲しかった機能：**

- レスポンスヘッダを設定できる。
- レスポンスを簡単に切り替えることが出来る。
- リクエスト、レスポンスの内容を確認することができる。
- (あると嬉しい) リクエスト内容によってレスポンスを切り替えることが出来る。

# instant-mock
## 使い方
作ったモックサーバはこちらです。
[https://github.com/arenahito/instant-mock](https://github.com/arenahito/instant-mock)

細かい説明は後にして、まずは動かしてみます。
[Node.js](https://nodejs.org/en/) 製なので、[Node.js](https://nodejs.org/en/) をインストールしてnpmが使えるようにしてください。
npmが使えるようになったら、下記コマンドでグローバルにインストールします。

```sh
npm install -g instant-mock
```

あとは、モックデータを格納する適当なディレクトリに移動して初期化＆起動するだけです。

```sh
cd (お好きなディクトリ)
instant-mock init
instant-mock
```

無事に起動したら、ブラウザで [http://localhost:3000](http://localhost:3000) にアクセスしてみてください。下記のようなコンソールが表示されたら成功です。

![init.png](https://qiita-image-store.s3.amazonaws.com/0/73867/78fd5b19-2a8c-1b0b-601d-4cb38fefadb0.png)

右側に表示されているのが、`instant-mock init`コマンドで作成したサンプルのモックAPIです。
右端にはレスポンスを切り替えるためにセレクトボックスが表示されています。レスポンスの作り方は後ほど。

すべてのモックAPIは http://localhost:3000/mock 配下にマウントされますので、ブラウザやcurlで [http://localhost:3000/mock/users](http://localhost:3000/mock/users) にアクセスしてみてください。
JSONが返却されたらコンソールに戻りましょう。下記のようにリクエスト／レスポンスの内容が表示されています。

![logs.png](https://qiita-image-store.s3.amazonaws.com/0/73867/43586a70-5345-bbf2-e40e-ad8a88aaf21b.png)

## API定義
モックAPIの定義ファイルは、`mock` ディレクトリ配下に用意します。
ディレクトリ名からURLパスが自動生成されます。`mock/api-name/@METHOD` というディレクトリであれば、`METHOD: http://localhost:3000/mock/api-name` にマッピングされます。`METHOD` は、get/post/put/patch/deleteからお好きなものをどうぞ。
ルートパラメータを使用したい場合は、`$PARAM` ディレクトリを作ればOKです。`mock/api-name/$id/@get` だと、`GET: http://localhost:3000/mock/api-name/:id` にマッピングされます。`:id` は可変ですね。

`instant-mock init` を実行するとサンプルの定義ファイルが出来ますので、参考にしてください。

## リクエストパーサ
リクエストに対するレスポンスは、"parser-" で始まるYAML/JSファイルで定義します。
下記ファイルを作ってinstant-mockを再起動し、`http://localhost:3000/mock/users` にアクセスしてください。YAMLファイルで定義した内容が返却されます。

**./mock/books/@get/parser-default.yml:**

```yaml
status: 200                   # Response status code.
headers:                      # Response headers.
  Content-Type: application/text
rawBody: 'test body'          # Response body.
```

## レスポンスボディを別ファイルに記述
前節ではレスポンスボディをYAMLファイルに直接記述しましたが、下記のように別ファイルとすることも出来ます。
別ファイルを作った場合は、`rawBody` ではなく、`body` にファイル名を設定してください。

**./mock/books/@get/body.json:**

```json
{
  "key": "value"
}
```

**./mock/books/@get/parser-default.yml:**

```yaml
status: 200
headers:
  Content-Type: application/json
body: 'body.json'    # Response body file.
```

## リクエスト内容によってレスポンスを切り替える
モックだし固定データを返せれば良いんだけど、リクエストに合わせて変えられると嬉しいな～ |ω・`）チラ
という方のために、簡易的にリクエストからレスポンスにマッピングする機能があります。

下記のように記述すると、ルーティングパラメータの `id` によってレスポンスを切り替えることが出来ます。
`http://localhost:3000/mock/books/1` にアクセスすると "book 1"、`http://localhost:3000/mock/books/3` だと404が返却されます。

**./mock/books/$id/@get/parser-default.yml:**

```yaml
- if:
    params:
      id: 1
  then:
    rawBody: 'book 1'

- if:
    params:
      id: 2
  then:
    rawBody: 'book 2'

- then:
    status: 404
```

`if` には、params/query/bodyを指定することができます。
これらは "and" 条件となりますので、すべてに一致した場合に `then` で定義したレスポンスが返却されます。

- **params:** ルートパラメータ
- **query:** クエリ文字列パラメータ
- **body:** ボディのJSONデータ

## もっとすごいことがしたい
YAMLファイルの条件指定は簡易的なものです。条件は完全一致で "and" のみです。
もっとすごいことがしたい方は、YAMLではなくJavaScriptを使用することが出来ます。

作り方は簡単で、パラメータとしてリクエストオブジェクトを受け取り、レスポンス定義を返却する関数をexportするだけです。
リクエストオブジェクトは [Express.js](http://expressjs.com/) の [Request](http://expressjs.com/en/4x/api.html#req) をそのまま渡していますので、煮るなり焼くなりお好きにどうぞ。

**./mock/shelves/:id/@get/parser-default.js:**

```js
exports.default = function (req) {
  return {
    status: 200,
    headers: {
      'content-type': 'application/text',
    },
    rawBody: 'your book is ' + req.params.id,
  };
};
```

# おわりに
単体テストだけでいきなり結合したら爆発したということにならないためにも、モックサーバを使ったテストをお勧めします。
対向サーバがエラーを返すデータを作れない (作るのが大変) という場合にも、モックサーバがあれば幸せになれます。
使えるものは使って手を抜きつつも、きっちりテストしましょう (・∀・)ﾉｼ