json-serverを使って簡単にAPIをmockする

# はじめに :sleepy:

#### JSON Server
[https://github.com/typicode/json-server](https://github.com/typicode/json-server)

* 簡単なものならコーディング不要でサクッとAPIをモックできるNode.jsのライブラリ
* 詳しく使い方を知りたい場合は上記リポジトリのREADMEを読んだほうが良い

#### まえがき
まだAPIが用意できていないけど、フロント側の実装を進めたいときに便利です。
本記事ではサクッと使える簡単なモックと、応用として以下2つの方法を記載したいと思います。

1. POSTリクエストで任意のレスポンスを返す
2. サーバーサイドエラーのモックする


# サクッと使う

任意のディレクトリを作成し移動後、 json-server をインストールする

```zsh

$ npm install json-server --save-dev
```

db.json を作成し、モックしたいデータを挿入

```json:db.json
{
  "molcars": [
    {
      "name": "ポテト",
      "favoriteFood": "ニンジン"
    },
    {
      "name": "シロモ",
      "favoriteFood": "レタス"
    }
  ],
  "episodes": [
    {
      "id": 1,
      "title": "渋滞は誰のせい？"
    },
    {
      "id": 2,
      "title": "銀行強盗をつかまえろ！"
    }
  ]
}
```

これでおわり！
あとは以下コマンドを叩いて json-server を起動し……

```zsh

$ json-server --watch db.json
```

curlなりなんなりで、このように db.json に記載したデータが返却されます。

```zsh
$ curl -X GET 'http://localhost:3000/molcars'
[
  {
    "name": "ポテト",
    "favoriteFood": "ニンジン"
  },
  {
    "name": "シロモ",
    "favoriteFood": "レタス"
  }
]
```

```zsh

$ curl -X GET 'http://localhost:3000/episodes'
[
  {
    "id": 1,
    "title": "渋滞は誰のせい？"
  },
  {
    "id": 2,
    "title": "銀行強盗をつかまえろ！"
  }
]
```

# 応用

上記だけじゃ機能として物足りない場合、
json-server をモジュールとして使用することでほしい機能を追加できます。

## json-server をモジュールとして使う

公式のREADMEにあるシンプルなコードです。

```js:server.js

const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()

server.use(middlewares)
server.use(router)
server.listen(3000, () => {
  console.log('JSON Server is running')
})
```

以下コマンドで起動可能

```zsh

$ node server.js
```

この時点でできることはサクッと編と基本的に同じで、
上記コマンドで起動したあとにcurlするとdb.jsonの値が同じように返却されます。

というわけで、上記のコードにほしい機能を追加していきましょう。

### POSTリクエストで任意のレスポンスを返す

サクッと編で作成したモックでは、
POSTでリクエストを送ると実際に以下のようなレスポンスが返却され、
なおかつこのレスポンスと同じデータが `db.json` に勝手に挿入されます。

```json
{  
  "id":2
}
```
(idの値は自動でインクリメントされます。)

なのでPOSTでリクエストした際のレスポンスを設定したい場合や、
勝手に `db.json` に値を追加してほしくない場合は
POSTリクエストを `server.js` 内でGETとして処理するように変更します。

```js:server.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()

server.use(middlewares)

/** ↓ POST を GET として処理する場合はここを追加 ↓ */
server.use(jsonServer.bodyParser) // POST, PUT, PATCH を扱うために必要
server.use((req, res, next) => {
  if (req.method === 'POST') {
    // POST のリクエストを GET に変換
    req.method = 'GET'
  }
  next()
})
/** ↑ POST を GET として処理する場合はここを追加 ↑ */

server.use(router)

server.listen(3000, () => {
  console.log('JSON Server is running')
})
```

あとは先程と同様に起動して

```zsh

$ node server.js
```

curlでレスポンスが返ってくることが確認できます。

```zsh
$ curl -X POST 'http://localhost:3000/molcars'
[
  {
    "name": "ポテト",
    "favoriteFood": "ニンジン"
  },
  {
    "name": "シロモ",
    "favoriteFood": "レタス"
  }
]
```

### サーバーサイドエラーのモック方法

公式のREADMEに記載されていますが、
レスポンスを変更したい場合は router.render メソッドを上書きします。

任意のステータスコードおよびエラーメッセージを返す場合は
 `server.js` を以下のように変更します。

```js:server.js

const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()

server.use(middlewares)

server.use(router)

server.listen(3000, () => {
  console.log('JSON Server is running')
})

/** ↓ サーバサイドエラーをモックしたい場合はここを追加 ↓ */
router.render = (req, res) => {
  // ステータスコードを設定
  res.status(500).jsonp({
    error: "PUI PUI"
  })
}
/** ↑ サーバサイドエラーをモックしたい場合はここを追加 ↑ */
```

これも同様に起動すれば

```zsh

$ node server.js
```

叩いた際に **ステータスコード500** と 
**エラーメッセージ「"error": "PUI PUI"」** が返却されるようになります。

```zsh

$ curl -X GET 'http://localhost:3000/molcars'
{
  "error": "PUI PUI"
}
```