Express/TypescriptでAPIサーバーを構築しており
Jestとsupertestを用いてルーティングテストを作成しました。
その時、明らかにテストがfailするなずなのにpassしてしまう
問題😭 があり、その原因を調べ対処しました。
補足
環境
- Node: v10.15.2
- nodeenvを利用し、プロジェクトごとにバージョンを指定することがおすすめです。
- @types/jest: 24.0.11
- @types/supertest: 2.0.7
Jest
- Facebook製のjavascriptテストフレームワーク。
- アサーションだけでなく、テストカバレッジなども行ってくれる万能ライブラリ。
supertest
- Http通信のテストに特化したテストツール。
テスト対象のルーティング
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
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するようになりました🙌