これは、なにをしたくて書いたもの?
TypeScriptでExpressを使ってみようかなと。
簡単なGET、POST、それからテストを書いてみたいと思います。
環境
今回の環境は、こちらです。
$ node --version v16.13.0 $ npm --version 8.1.0
準備
まずは、TypeScriptとJestを使う準備までしておきます。
$ npm init -y $ npm i -D typescript $ npm i -D -E prettier $ npm i -D jest @types/jest ts-jest $ npx ts-jest config:init $ mkdir src test
tsconfig.json
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "baseUrl": "./src", "outDir": "dist", "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true }, "include": [ "src" ] }
.prettierrc.json
{ "singleQuote": true }
Expressをインストールする
Node.js上なので、@types/node
をインストール。
$ npm i -D @types/node
それから、Expressとtypesをインストール。
$ npm i express $ npm i -D @types/express
現時点での依存関係は、こんな感じ。
"devDependencies": { "@types/express": "^4.17.13", "@types/jest": "^27.0.3", "@types/node": "^16.11.9", "jest": "^27.3.1", "prettier": "2.4.1", "ts-jest": "^27.0.7", "typescript": "^4.5.2" }, "dependencies": { "express": "^4.17.1" }
ソースコードを書く
それでは、TypeScript+Expressでソースコードを書いてみます。
こちらを見ながら
こんな感じで作成。
src/app.ts
import express from 'express'; import bodyParser from 'body-parser'; export const app = express(); app.use(bodyParser.json()); app.get('/echo', (req, res) => { const message = req.query['message']; res.send(`Hello ${message}!!`); }); app.post('/echo', (req, res) => { const message = req.body['message']; res.send({ message: `Hello ${message}!!` }); });
GETならQueryString、POSTならBodyからメッセージを受け取って返すアプリケーションです。
今後のテストのために、起動部分は切り離しておきます。
src/server.ts
import { app } from './app'; const port = 3000; app.listen(port, () => console.log(`[${new Date().toISOString()}] start server[${port}]`) );
では、ビルド。
$ npx tsc
動作確認してみます。
起動。
$ node dist/server.js [2021-11-20T09:27:47.527Z] start server[3000]
確認。
## GET $ curl localhost:3000/echo?message=Express Hello Express!! ## POST $ curl -H 'Content-Type: application/json' localhost:3000/echo -d '{"message": "Express"}' {"message":"Hello Express!!"}
OKですね。
テストを書く
続いては、テストを書いてみます。
Jest+Expressでテストを書くにはどうしたら?と思ったのですが、Jestのページにヒントが書いてありました。
Testing Web Frameworks / Express.js
How to test Express.js with Jest and Supertest | Through the binary
SuperTestというものを使うみたいです。
SuperTestは、SuperAgentを利用したHTTPのアサーションライブラリです。
SuperAgentは、Node.jsやブラウザで使えるHTTPクライアントです。
SuperAgent — elegant API for AJAX in Node and browsers
というわけで、SuperTest、SuperAgentおよび型宣言をインストール。
$ npm i -D supertest superagent @types/supertest @types/superagent
SuperTestの依存関係にSuperAgentはついてくるんですけどね。
バージョン。
"@types/superagent": "^4.1.13", "@types/supertest": "^2.0.11", "superagent": "^6.1.0", "supertest": "^6.1.6",
テストコードは、こんな感じに。
test/app.test.ts
import request from 'supertest'; import { app } from '../src/app'; test('get /echo', () => { return request(app) .get('/echo?message=Express') .then((response) => { expect(response.status).toEqual(200); expect(response.text).toEqual('Hello Express!!'); }); }); test('post /echo', () => { return request(app) .post('/echo') .set('Content-Type', 'application/json') .send({ message: 'Express' }) .then((response) => { expect(response.status).toEqual(200); expect(response.body).toEqual({ message: 'Hello Express!!' }); }); });
SuperTestのrequest
に、app
のインスタンスを渡します。
最初にソースコードを書いた時に、app#listen
を呼び出す部分を別ファイルにしたのはこれが理由ですね。
では、テストを実行します。
$ npx jest
結果。
PASS test/app.test.ts ✓ get /echo (28 ms) ✓ post /echo (20 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 4.035 s, estimated 7 s Ran all test suites.
OKですね。
まとめ
TypeScriptでExpressを使い、テストも含めて書いてみました。
TypeScript+Expressの環境をどうやって作るのかがExpress側にはないので、いろいろ情報を探してみましたが
だいたいこんな感じで良さそうかなと思います。
まだまだTypeScriptに慣れていない感じなので、頑張っていきましょう…。