Express/Typescriptのルーティングテストが全てPassしてしまう対処法

Express/TypescriptでAPIサーバーを構築しており

Jestとsupertestを用いてルーティングテストを作成しました。

その時、明らかに`テストがfailするなずなのにpassしてしまう`問題😭 があり、その原因を調べ対処しました。 


## 補足

### 環境
- Node: v10.15.2
 - [nodeenv](https://github.com/nodenv/nodenv)を利用し、プロジェクトごとにバージョンを指定することがおすすめです。
- @types/jest: 24.0.11
- @types/supertest: 2.0.7

### Jest

- Facebook製のjavascriptテストフレームワーク。
- アサーションだけでなく、テストカバレッジなども行ってくれる万能ライブラリ。

https://jestjs.io/

### supertest

- Http通信のテストに特化したテストツール。

https://www.npmjs.com/package/supertest


## テスト対象のルーティング
```app.ts
import * as express from 'express';

class App {

  public express: express.Application;

  constructor() {
    this.express = express();
    this.routes();
  }

  public routes() {
    // root('/')にGETメソッドでリクエストすると、status_code:200 で body:{message:"Hello Express!"} が返る
    this.express.get('/', (req, res) => res.json({message:"Hello Express!"}));
  }

  public start() {
    this.express.listen(3333, () => console.log(`Example app listening on port 3333!`));
  }
}

export default App;

```

# ○ 修正前

## テスト

```app.spec.ts

import * as request from "supertest";
import App from "../src/app";

describe("GET /", () => {
  it("return 200 and correct message", () => {
    const app = new App();
    request(app.express)
      .get("/")
      .expect(400) // あえてfailするテストを追加
      .expect({message: 'Hello Express!'});
  });
});

```

## 結果
```
$ yarn test
yarn run v1.15.2
$ jest
 PASS  test/app.spec.ts
  GET /
    ✓ return 200 (10ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.08s
```

テストがpassしてしまっている 😱。

## 問題

- status_codeは200が返るのに、400を返すことを想定したテストでもpassしてしまいました。

- 他のテストを書いていて気づいたのですが、status_code以外でも明らかにfailするテストを書いてもpassするようになっていました。

## 原因

[How to test Express.js with Jest and Supertest](http://www.albertgao.xyz/2017/05/24/how-to-test-expressjs-with-jest-and-supertest/)

> That return is crucial, otherwise your tests will get stuck.

'return'は非常に重要であり、さもなければあなたのテストは行き詰まる

> Notice that without that return, the test will always pass.

returnを付けないと、必ずテストがpassしてしまう

---

supersetのテストの方法として、必ずステートメントを返す必要があり、
今回の場合は`return`がなく、何も返されていなかったため、全てのテストでpassすることになっっていました。


## 修正方法
`expected`の値を`return`させる。

# ○ 修正後

## テスト

```app.spec.ts
import * as request from "supertest";
import App from "../src/app";

describe("GET /", () => {
  it("return 200", () => {
    const app = new App();
    // 'return'を追加した
    return request(app.express)
      .get("/")
      .expect(400) // あえてfailするテストを追加
      .expect({ message: 'Hello Express!' });
  });
});

```

## 結果
```
$ yarn test
yarn run v1.15.2
$ jest  && tsc --noEmit
 FAIL  test/app.spec.ts (10.787s)
  GET /
    ✕ return 200 (47ms)

  ● GET / › return 200

    expected 400 "Bad Request", got 200 "OK"

      at Test.Object.<anonymous>.Test._assertStatus (node_modules/supertest/lib/test.js:268:12)
      at Test.Object.<anonymous>.Test._assertFunction (node_modules/supertest/lib/test.js:283:11)
      at Test.Object.<anonymous>.Test.assert (node_modules/supertest/lib/test.js:173:18)
      at Server.localAssert (node_modules/supertest/lib/test.js:131:12)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        11.801s
Ran all test suites.
error Command failed with exit code 1.
```

テストは想定通りfailするようになりました🙌