Mockを使ってLambdaをテストする

## はじめに
サーバーレスなLambda関数のテスト方法を自分なりにメモしています。
Lambda関数のテスト０の状態から手を動かした結果をメモしているので、おかしな内容があればFBお願い致します。

### Lambda関数テスト方法
そもそもLambda関数のテストは、フェーズが大きく３つに分類できます。

```:テスト方法
1. 関数単体のユニットテスト
- chai,MochaなどのNodejsのライブラリを使用する。
- [AWS Lambdaのユニットテストのベストプラクティス(Node.js)](https://qiita.com/horike37/items/034f731f1b40c5a28e74 )

2. モックを使用したテスト
- aws-lambda-mock-contextを使用して、擬似Lambdaをローカル環境で実行してテストする。

3. Lambda上でステージングテスト
- 実際にLambda関数をステージング環境にリリースしてテストする。
```

今回は **2. モックを使用したテスト** の手順をまとめます。
基本的には[AWS LambdaのテストでJestの恩恵を享受しまくろう](https://note.mu/k_morihiro/n/n987e4d2241b3)を参考にさせて頂きました。

### 手順

#### 1. テスト用のライブラリインストール
```terminal:terminal
# Installation
$ npm install --save-dev jest
$ npm install --save-dev aws-lambda-mock-context
```
[公式npm: aws-lambda-mock-context](https://www.npmjs.com/package/aws-lambda-mock-context)


#### 2. テスト用にパラメータを作成する
実際にAPIGatewayに入ってくるパラメータを確認して、サンプルパラメータを作成する。
specディレクトリを作成して、パラメータのJSONを作成します。
(※各自パラメータが違うため、CloudWatchなどのログを見ながらパラメータを作成します。)

```javascript:spec/event_data.js
module.exports = {
  resource: "/",
  path: "/",
  httpMethod: "POST",
  headers: null,
  multiValueHeaders: null,
  queryStringParameters: null,
  multiValueQueryStringParameters: null,
  stageVariables: null,
  requestContext: {
    path: "/dev",
    accountId: "×××××××",
    resourceId: "",
    stage: "dev",
    domainPrefix: "",
    requestId: "",
    identity: {
      cognitoIdentityPoolId: null,
      cognitoIdentityId: null,
      // apiKey: "",
      cognitoAuthenticationType: null,
      userArn: null,
      // apiKeyId: "",
      userAgent: "",
      accountId: null,
      caller: null,
      sourceIp: "",
      accessKey: "",
      cognitoAuthenticationProvider: null,
      user: null
    },
    domainName: "",
    resourcePath: "/",
    httpMethod: "POST",
    extendedRequestId: "",
    apiId: ""
  },
  body: {
    "token": "",
    "team_id": "",
    "api_app_id": "",
    "event": {
        "type": "reaction_added",
        "user": "",
        "item": {
            "type": "",
            "channel": "",
            "ts": ""
        },
        "reaction": "",
        "event_ts": ""
    },
    "type": "event_callback",
    "event_id": "",
    "event_time":,
    "authed_users": [
        ""
    ]
},
  isBase64Encoded: false
};
```

#### 3. テストコードを書く
> Jestはデフォルト設定で ___test__ ディレクトリ配下にあるファイルもしくは xxx.spec.js 、 xxx.test.js というファイルを自動的に読み込んでテストを実行してくれます。今回は spec/handler.spec.js というファイルを用意し、以下のようにテストを書きます。
[AWS LambdaのテストでJestの恩恵を享受しまくろう](https://note.mu/k_morihiro/n/n987e4d2241b3)

とのことなので、specディレクトリ以下にhandler.spec.js というファイルを用意

```javascript:spec/handler.spec.js
'use strict'
const context = require('aws-lambda-mock-context');
const { app } = require('../handler'); //メインのスクリプトファイル
const event = require('./event_data'); //作成したパラメータファイル


describe('handler.app()', () => {
  describe('when body.event.type is reaction_added', () => {
    it('returns a statusCoade 200', async () => {
      const response = await app(event, context(), function(){});
      console.log(context);
      expect(response.statusCode).toBe(200);
    });

    it('returns a body is results', async () => {
      const response = await app(event, context(), function(){});
      expect(response.body).toEqual("results");
    });
  });
});

```

##### ポイント
`npm testコマンド` でjestを実行するように書き直しておく。

```json:package.json
{
  "name": "アプリ名",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest" ←npm testコマンドでjestを実行するように書き直す
  },
  :
  :
}
```




#### 4. テストを実行する

```terminal:terminal
npm test

>アプリ名@1.0.0 test /Users/~~~/~~app
> jest

 PASS  spec/handler.spec.js
  handler.app()
    when body.event.type is reaction_added
      ✓ returns a statusCoade 200 (26ms)
      ✓ returns a body is results (2ms)

  console.log spec/handler.spec.js:11
    [Function]

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.138s
Ran all test suites.
```

実行されていることを確認。

##### 参考サイト
[AWS LambdaのテストでJestの恩恵を享受しまくろう](https://note.mu/k_morihiro/n/n987e4d2241b3)
[AWS Lambdaのユニットテストのベストプラクティス(Node.js)](https://qiita.com/horike37/items/034f731f1b40c5a28e74 )