← NestJS コース
34. ユニットテスト — Test.createTestingModule
NestJS は @nestjs/testing でテスト用の DIコンテナを提供します。Test.createTestingModule({ providers: [...] }) でテスト専用のモジュールを組み立て、.compile() した後 module.get(UsersService) で対象のインスタンスを取り出します。テストランナーには Jest を使うのが既定で、describe / it / expect でアサーションを書きます。
実務でのサービス単体テストの定石は、対象サービスが依存する他のプロバイダ(リポジトリや外部 API クライアントなど)をモックに差し替えることです。providers に { provide: UsersRepository, useValue: モック } のように useValue でモックを登録すれば、本物の DB に触れずにロジックだけを検証できます。既存モジュールの構成を流用しつつ一部だけ差し替えたいときは overrideProvider(Token).useValue(モック) が便利です。
つまずきポイントは、何をモックすべきかの線引きです。テスト対象そのものは本物を使い、それが依存するものだけをモックにします。すべてをモックにすると「モックが返す値を確認しているだけ」で実ロジックを検証できません。また Scope.REQUEST なプロバイダは module.get では取り出せず resolve を使うなど、スコープによって取り出し方が変わる点にも注意します。
サンプルコード(フレームワーク環境が必要なため表示のみ)
import { Test, TestingModule } from "@nestjs/testing";
import { UsersService } from "./users.service";
import { UsersRepository } from "./users.repository";
describe("UsersService", () => {
let service: UsersService;
// 依存(リポジトリ)はモックに差し替える
const repoMock = { findOne: jest.fn() };
beforeEach(async () => {
const moduleRef: TestingModule = await Test.createTestingModule({
providers: [
UsersService, // テスト対象は本物
{ provide: UsersRepository, useValue: repoMock }, // 依存はモック
],
}).compile();
service = moduleRef.get<UsersService>(UsersService);
});
it("finds a user by id", async () => {
repoMock.findOne.mockResolvedValue({ id: 1, name: "Alice" });
const user = await service.findOne(1);
expect(user.name).toBe("Alice");
});
});
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗