はじめに
DBへのinsert処理を含むAPIのApplication ServiceレベルでのJestのテスト例です(with TypeORM)。固定のfixtureデータが既にDBに挿入済みの前提で、update処理の場合も考え方は同じです。
サンプルコード
describe("UserApplicationService", () => {
describe("createUser", () => {
it("should create a user", async () => {
// 初期状態のレコード数の確認
const [, userCountBefore] = await userRepository.findAndCount();
// 関数の実行
const createdUser = await UserApplicationService.createUser(
{
name: userFixture.admin.name,
role: Role.Admin
}
);
// 関数実行後のレコード数のカウント
const [, userCountAfter] = await userRepository.findAndCount();
// DBにレコードが追加されているか確認(されていればエラーを出力、データのリセットの必要もなし)
assert.strictEqual(userCountAfter, userCountBefore + 1);
// アサーションの準備が必要であればここで(DBから特定のレコードの状態を取ってくるなど)
// アサーション
try {
assert.strictEqual(
createdUser.name,
userFixture.admin.name
);
assert.strictEqual(
createdUser.role,
Role.Admin
);
} finally {
// DBのfixtureデータのリセット
// finally節で包まないと上記どこかでfailした際にリセットされない
await userRepository.remove(createdUser);
}
});
});
});
(mochaなどと違ってテストのブロックごとに個別にafter()
等ができないようなので、各it
内でリセットするようにしています。)
ポイントは以下の通りです。
- 対象の関数を実行してアサーションする前にDBにレコードが追加されているかを確認
- 対象の関数によってinsertされたDBのレコードを、アサーションした後に削除(fixtureデータをリセット)。insertではなくupdateの場合(もしく複数テーブルにおけるinsert/updateの組み合わせ)も同様にここでリセット処理を行う。
- リセット処理はfinally節で包む(そうしないとassertでfailした際にリセット処理が走らなくなる)
テスト用のfixtureに関しては、この記事の「Fixtureをきちんと設計しているか」というセクションにも関連した内容を書いています。
まとめ
finally
節で包むのを忘れてしまい、後続のテストがコケた際に原因を突き止めるのに少し手間がかかったことがあったので、今回軽くまとめておきました。