7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Jestを使ってexpressをTDDをしたい

Last updated at Posted at 2020-08-09

事の発端

TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング を見てからTDDに興味津々です。
というか、長い間開発やってるのだから、この辺もちゃんと出来ないとだめだと思って勉強中です。

今回のターゲット

  • 現在社内で構築しているbackendをTDDできるようにする

主な環境

  • express
  • jest
  • typescript
  • typeorm
  • mariadb

一応、全部コンテナで実行できるようになっています。(ハズ)
詳細はこちらを参照

準備

自分は最近、npmでは無くyarn を使用しているので、以降すべてyarn を
使用することを前提に説明していきます。

ディレクトリの構成は主に以下のような感じです。

.
├── package.json
├── src
│   ├── entity
│   │   └── User.ts
│   ├── index.ts
│   ├── migration
│   └── server.ts
└── test
    └── server.spec.ts

必要なパッケージのインストール

多分、以下のパッケージを入れておけば良いのかと。
自分の場合は、ORMとしてtypeormを使っているので、typeormもインストールし
プロジェクトの作成もしています。

$ yarn global add typeorm
$ typeorm init --name app --database mysql
$ cd app
$ yarn add \
         @types/express \
         @types/express-session \
         @types/jest \
         @types/node \
         @types/supertest \
         @typescript-eslint/eslint-plugin \
         @typescript-eslint/parser \
         cors \
         eslint \
         eslint-config-prettier \
         eslint-plugin-prettier \
         express \
         express-session \
         jest \
         mysql2 \
         prettier \
         reflect-metadata \
         supertest \
         ts-jest \
         ts-node \
         tsconfig-paths \
         typescript

express サーバの作成

まずはテストしやすいようにexpressのサーバを切り出します。

server.ts
import express from "express";

export class AppServer {
  public app: express.Application;

  constructor() {
    this.app = express();
    this.setupRoutes();
  }

  public setupRoutes() {
    this.app.get("/", (req, res) => {
      res.json({ message: "AppServer started" });
    });
  }

  public start() {
    this.app.listen( {port: 4000}, () => {
      console.log(`server on http://localhost:4000`);
    });
  }
}

package.json を修正

「yarn test」でテストを実行できるようにpackage.json を修正。

package.json
   "scripts": {
-     "start": "ts-node src/index.ts"
+     "start": "ts-node src/index.ts",
+     "test": "jest"
   },

jest の設定を何もしてないと以下のように「import」が使えないとエラーを
出すので、jestでtypescriptのソースを解釈できるように以下のように追記します。
自分の場合、テストコードは「test」ディレクトリに保存し、命名規則的には「〜.spec.ts」に
しているため、「testMatch」の部分にその旨を設定します。

Cannot use import statement outside a module
package.json
   "scripts": {
      "start": "ts-node src/index.ts",
      "test": "jest"
-   }
+   },
+   "jest": {
+     "moduleFileExtensions": [
+       "ts",
+       "js"
+     ],
+     "transform": {
+       "^.+\\.ts$": "ts-jest"
+     },
+     "globals": {
+       "ts-jest": {
+         "tsConfig": "tsconfig.json"
+       }
+     },
+     "testMatch": [
+       "**/test/**/*.spec.ts"
+     ]
+   }

tsconfig.json を修正

「export default〜」で定義された定義をimportできるようにするため、
tsconfig.json に以下を追記します。
※ 認識あっているんだろうか?

tsconfig.json
{
   "compilerOptions": {
      "lib": [
         "es5",
         "es6"
      ],
      "target": "es5",
      "module": "commonjs",
      "moduleResolution": "node",
      "outDir": "./build",
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
+      "esModuleInterop": true,
      "sourceMap": true
   }
}

ここまでで設定関連は終了のはず。

テストソースを準備する

とりあえずbackend サーバとしては、GET で「/」にアクセスすると
「{message: "AppServer started"}」を返すようになっているため、
ステータスコード200を受けて、messageを正しく取得出来ているかのテストを準備します。

express をユニットテストする際には、どうもsupertest なるモジュールを使用するようなので、
こちらを使用します。
※ express のテストがこうだったし、他を探してもコレが一般的なのかと今の所思っています。

server.spec.ts
import request from "supertest";
import { AppServer } from "../src/server";

describe("GET /", () => {
  it("return 200 and correct message", () => {
    const server = new AppServer();

    return request(server.app)
            .get("/")
            .expect(200)
            .expect({message: "AppServer started"});
  });
});

テストの実行

「yarn test」を実行してテストがパスすることを確認します。
今回は全部がコンテナ内で動作できるようにしているため、
以下を実行すればできるはずです。

$ git clone git@github.com:shun/tdd-express-typescript.git
$ cd tdd-express-typescript
$ docker-compose pull # 必要に応じて
$ docker-compose up -d
$ docker-compose exec -u node express bash
node@b51cacc0699d:~/app$ yarn test
yarn run v1.22.4
warning package.json: No license field
$ jest
 PASS  test/server.spec.ts
  GET /
    ✓ return 200 and correct message (34 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.998 s
Ran all test suites.
Done in 3.71s.

これでやっとスタート地点に立てたかなと。。。
後は、これにtypeormでDBにアクセスしてデータを入れたり、取得したりすれば
思ったようなTDDができるはず。
これからTDDがんばるぞー。

長くなりましたが、ここまでお付き合いしていただきありがとうございます。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?