Lesson 5
NestJSにおけるテスト
Lesson 5
Chapter 1
@nestjs/testingのインストール
NestJS
でテストを記述するために@nestjs/testing
をインストールします。
@nestjs/testingが入っている人
NestJSのプロジェクトを作成した時点で@nestjs/testing
がすでに入っている人はこのChapterは飛ばして大丈夫です。次の「Chapter5.2
テストを書いて実行してみる」まで進みましょう。自分のプロジェクトに@nestjs/testing
が入っているかは「package.json」を確認して見てみましょう。
@nestjs/testingのインストール
@nestjs/testing
は以下のコマンドでインストールします。本番用のディレクトリに含めてたくないため-D
を付与してdevDependencies
へ入れます。
npm install -D @nestjs/testing
これで@nestjs/testing
のインストールは完了です。次のChapterでは実際にテストを書いていきます。

Lesson 5
Chapter 2
テストを書いて実行してみる
このChapterでは実際にNestJS
のテストを書いていきます。
テストの種類
NestJS
のテストには以下の種類があります。
種類 | 説明 |
---|---|
Unit Testing | DIを使用せず、単一のクラスをテストする。対象のクラスを手動でインスタンス化し、対象のクラスが役割を満たすかをテストする。 |
Integration Testing | クラスやモジュールの相互作用をテストする。実際にDIを使用し、ControllerとServiceやServiceとRepositoryは意図した関係で振る舞いを行えているかを確認する。 |
End-to-end Testing | 実際にAppを使用するユーザーと本番システムとの相互関係をカバーするためのテスト。その相互関係をカバーすることでAppの要件を満たしているかを確認できる。 |
テストを書く準備
今回はUnit Test
を書いていきます。Unit Test
はひとつの関数レベルから一番手軽に書けるテストなのでテストを書くにはまずUnit Test
から始めるのがオススメです。今回は「todo.service.ts」のUnit Test
を書いていきましょう。以下のコマンドでテスト用のファイルを作成します。
実務でのUnit Test
今回は単一のクラスや関数レベルでのUnit Testを行いますが、実務ではAPI単位でのUnit Testを行うことが多いです。理由としては関数やクラスを1つずつテストしていくと開発の工数に響いてしまうためです。テストの定義は現場によって異なる場合があるということは覚えておいてください。
Mac & Linux
~/nest-todo/src/services/todo
touch todo.service.spec.ts
Windows
~/nest-todo/src/services/todo
type todo.service.spec.ts
テストを書く
まずはひとつ簡単なテストコードを書いてみます。以下のコードをtodo.service.spec.ts
に書き込みます。以下のテストコードはtrue
がtrue
であることをテストしています。当たり前のことを言ってますがまずはテストが通ることと書いてみることを目指してみます。
describe('todo.service.ts', () => {
it('trueであること', () => {
expect(true).toBe(true);
});
});
上記コードを書いたら下記コマンドでテストを通してみます。
~/src
npm run test
すると以下の画像のようにテストがPASS
したことを確認できます。これが一連のテストの流れになります。
テストがPASSたことを確認
describeとit
describe
はテストのグループ化を行い、it
はテストの内容を記述します。describe
の中にit
を記述することでテストのグループ化を行うことができます。
expectとtoBe
expect
はテスト対象を引数にとり、toBe
は期待する結果を引数に取ります。これらはJest
の機能です。これらは基本的なテストの記述方法です。今後たくさん新しい知識が出てきますがその都度調べつつ使用していきましょう。
serviceのテスト
テストのための準備
テストの基本的な書き方がわかったところで「todo.service.ts」のテストを書いてみましょう。まずは下準備が必要なので下記をテストファイルに記述しましょう。コードの説明はコメントを参照してください。
todo.service.spec.ts
import { TestingModule, Test } from '@nestjs/testing';
import { TodoRepository } from 'src/repositories/todo/todo.repository';
import { TodoService } from './todo.service';
// Repositoryのメソッドをモック化
const mockTodoRepository = () => ({
getAllTodos: jest.fn(),
});
// TodoServiceのためのテストグループを作成
describe('TodoServiceTest', () => {
let service: TodoService;
let repository: jest.Mocked<TodoRepository>;
beforeEach(async () => {
// テストのためのmoduleを作成
const module: TestingModule = await Test.createTestingModule({
providers: [
TodoService,
{
provide: TodoRepository,
useFactory: mockTodoRepository,
},
],
}).compile();
// モジュールから取得したものを代入
service = module.get<TodoService>(TodoService);
repository = module.get<TodoRepository>(
TodoRepository,
) as jest.Mocked<TodoRepository>;
});
});
serviceのテストに注力する
今回はservice
のテストを書くことに注力します。理由はservice
はビジネスロジックを担当しアプリケーションの要件を中心に扱うレイヤーだからだからです。
repositoryのモック化
また、repository
をモック化しています。モック化とは実際の定義からテストコード上の定義に上書きすることを言います。これを行う理由としてはrepository
のメソッドをモック化することでrepository
のメソッドをテストすることなくservice
のテストに集中できるからです。また、repository
は3層アーキテクチャのデータアクセス層を担うため実際の挙動をテストするためにはデータベースとの接続が必要になります。service
の挙動をテストするという本来の目的とは逸れて、工数も嵩んでしまうため今回はモック化による簡略化でその懸念を回避しています。
serviceのテストを書く
それでは準備が済んだので以下のコードをテストコードとして書き込みましょう。
todo.service.spec.ts
describe('getAllTodos', () => {
it('正常系:serviceの返り値が期待通りであること', async () => {
const todos = [];
// モック化したメソッドの戻り値を設定
repository.getAllTodos.mockResolvedValue(todos);
// 実行
const result = await service.findAll();
// 返り値が期待通りであることを確認
expect(result).toEqual({ todos });
});
});
getAllTodosのテストグループ
describeでgetAllTodos
のテストグループを作成しています。テストのグループ化はテストの可読性を高めるために行います。また、テストのグループ化によってテストの実行を絞り込むことができます。例えば、getAllTodos
のテストグループだけを実行したい場合はnpm run test:watch -- -t getAllTodos
と実行しgetAllTodos
のテストのみwatchすることも可能です。
正常系のテスト
itで正常系:serviceの返り値が期待通りであること
というテスト名をつけています。テスト名は日本語でも英語でもどちらでも構いません。「正常系」という言葉はテストの内容を表すものではなく、テストの目的を表すものです。「正常系」は挙動に異常がなく正常に動作する状態のことを指します。
テストを実行する
それではテストを実行してみましょう。以下のコマンドを実行してください。画像のようにテストが通っていれば成功です。
~/nest-todo/
npm run test
getAllTodosのテストがパスしていることを確認
まとめ
今回はNestJSでユニットテストを書いてみました。ユニットテストはアプリケーションの品質を担保するために必要なテストです。また自動化していることで必要なタイミングで簡単に早く実行することができます。今回はNestJSでユニットテストを書く方法を紹介しましたが、他の言語でも同じようなテストの書き方ができます。また、ユニットテストは他のテストと比べて実行時間が短いため、テストの実行を絞り込むことができます。テストの実行を絞り込むことで、テストの実行時間を短縮することができます。アプリケーションの品質を担保するために積極的に取り入れるよう心がけていきましょう。
