🐕
【Jest】Express.jsのミドルウェアとして作成したモジュールの単体テスト
Express.jsのミドルウェアとして作成したモジュールの単体テストについてのメモです。
環境
- Express.js 4.18.2
- TypeScript 5.0.2
- jest 29.5.0
- sinon 15.0.3
- sinon-express-mock 2.2.1
考え方
- 単体テストとして以下を確認できればよさそう
- expressのRequest, Responseオブジェクトの中身の確認
- NextFunctionが呼ばれることの確認
- 内部で別の関数やメソッドを呼んでいる場合は別途モック化する
準備
- expressのRequest, Responseオブジェクトの中身の確認のため、expressのRequest, Responseのモックを用意する
-
sinon-express-mock
ライブラリを使用する
-
- NextFunctionが呼ばれることの確認のため、NextFunctionのスパイを用意する
-
sinon
ライブラリを使用する
-
npm i -D sinon-express-mock sinon @types/sinon-express-mock @types/sinon
スパイとは
関数やメソッドが呼び出された回数や呼び出された順番、引数を検証するために使用するオブジェクトです。
以下の記事が非常に参考となりました。ありがとうございます。
ミドルウェアとテストコードのサンプル
HTTPヘッダの x-user-id
から値を取得して、Responseオブジェクトの locals.userId
にセットするだけのミドルウェアです。
HTTPヘッダの x-user-id
がない場合は例外を発生させます。
サンプルのミドルウェア
import { Request, Response, NextFunction } from 'express';
export const middlewareSample = (req: Request, res: Response, next: NextFunction) => {
const userId = req.headers['x-user-id'];
if (!userId || userId === '') throw new Error();
res.locals.userId = userId;
next();
}
テストコード
import { middlewareSample } from '../expressMiddleware';
import sinon from 'sinon';
import { mockReq, mockRes } from 'sinon-express-mock'
describe('myMiddleware', () => {
it('should call next()', () => {
const req = mockReq(
// HTTPリクエストのヘッダーを設定
{
headers: {
"x-user-id": "12345"
}
}
);
const res = mockRes();
// スパイ:関数が呼ばれたかどうか、何回呼ばれたか、などをチェック(監視)するためのモノ
const next = sinon.spy();
middlewareSample(req, res, next);
// next()が呼ばれたことを確認する
expect(next.calledOnce).toBe(true);
// res.locals.userIdが正しいことを確認する
expect(res.locals.userId).toBe("12345");
});
it('should not call next()', () => {
const req = mockReq(
{
headers: {
"x-user-id": ""
}
}
);
const res = mockRes();
const next = sinon.spy();
// 例外が発生することを確認する
expect(()=>middlewareSample(req, res, next)).toThrowError();
// next()が呼ばれなかったことを確認する
expect(next.calledOnce).toBe(false);
});
});
以上です。
GitHubで編集を提案
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion