この記事は「Angular × Vite ユニットテスト入門|Vitestで始めるテスト完全ガイド」シリーズの一部です。
Angular ユニットテストの基本(Vitest対応)|デフォルトコードの意味を完全解説
Angularでコンポーネントを作成すると、ng generate component によってユニットテストコードが自動生成されます。
近年は高速なビルドツールであるViteと、テストランナーとしてVitestを組み合わせる構成が注目されています。
本記事では、Angular + Vite環境でのデフォルトテストコードの意味を1行ずつ丁寧に解説します。
初心者でも理解できるように、TestBedやfixtureの役割を中心に解説します。
前提:Angular × Vite × Vitest のテスト環境
従来のAngularではKarma + Jasmineが標準でしたが、現在は以下の構成が主流になりつつあります。
- ビルドツール:Vite
- テストランナー:Vitest
- テストユーティリティ:Angular Testing Library / TestBed
この構成のメリットは以下です。
- テスト実行が非常に高速
- HMR(ホットリロード)により開発効率が向上
- 設定がシンプル
その中でも、Angular標準のTestBedは引き続き重要な役割を持ちます。
デフォルトで生成されるテストコード
以下が ng generate component 実行時に生成される基本的なテストコードです。
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my-component';
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyComponent],
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
await fixture.whenStable();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
ここからは、このコードの意味を分解して解説します。
describe:テストスイートの定義
describe('MyComponent', () => {
describeはテストのまとまり(テストスイート)を定義します。
VitestでもJasmineと同様にdescribe / it構文が使用できます。
- 第一引数:テスト対象の名前
- 第二引数:テストの中身
beforeEach:テストの事前準備
beforeEach(async () => {
各テスト(it)実行前に毎回呼ばれる初期化処理です。
Angularのテストでは、コンポーネントの生成や依存関係の設定をここで行います。
TestBed.configureTestingModule:テスト用モジュールの定義
await TestBed.configureTestingModule({
imports: [MyComponent],
}).compileComponents();
TestBedはAngularのテスト専用DIコンテナです。
ここではテスト用のモジュールを定義しています。
なぜimportsにMyComponentを書くのか
最近のAngularでは「スタンドアロンコンポーネント」が主流です。
そのため、NgModuleではなくimportsに直接コンポーネントを指定します。
従来(NgModuleベース)との違い:
- 旧:declarationsに記述
- 新:importsに記述
compileComponentsの役割
.compileComponents();
コンポーネントのテンプレートやスタイルをコンパイルします。
非同期処理のため、awaitが必要です。
createComponent:コンポーネントの生成
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
ここで実際にコンポーネントインスタンスを作成します。
- fixture:テスト用のラッパー
- component:実際のコンポーネントインスタンス
fixtureとは何か
fixtureはコンポーネントのテスト操作を行うためのオブジェクトです。
主な役割:
- DOMの取得(fixture.nativeElement)
- 変更検知の実行(fixture.detectChanges())
- 非同期の安定化(fixture.whenStable())
whenStable:非同期処理の完了待ち
await fixture.whenStable();
Angular内部の非同期処理(Promiseやイベント)がすべて完了するまで待機します。
特に以下の場合に重要です。
- ngOnInitでAPI呼び出しがある
- async/awaitを使っている
- フォームやイベント処理がある
Vite + Vitest環境でも、この処理は有効です。
it:テストケースの定義
it('should create', () => {
expect(component).toBeTruthy();
});
個別のテストケースを定義します。
- it:テストの説明
- expect:検証処理
このテストは「コンポーネントが正常に生成されるか」を確認しています。
なぜこのテストが重要なのか
一見シンプルですが、このテストには以下の意味があります。
- DIが正しく解決されているか
- テンプレートが正常にコンパイルされるか
- 初期化処理でエラーが出ていないか
つまり、最低限の「起動確認テスト」です。
Vite環境での注意点
Angular + Vite + Vitest環境では以下に注意してください。
非同期処理は基本的にawaitを使う
VitestはPromiseベースのテストに強いため、以下が推奨です。
- async / await を使う
- fakeAsyncは必要な場面だけ使う
zone.jsの扱い
Angularのテストはzone.jsに依存していますが、Vite環境では設定によっては軽量化されます。
そのため、
- whenStableは引き続き有効
- ただし不要なケースもある
という点を理解しておくと良いです。
よくある改善ポイント
デフォルトコードは最低限のため、実務では以下を追加します。
detectChangesの明示実行
fixture.detectChanges();
初回の変更検知を明示的に実行することで、テンプレートの状態が安定します。
DOMテストの追加
const element = fixture.nativeElement;
expect(element.querySelector('h1').textContent).toContain('Hello');
ユーザー視点のテストを書くことが重要です。
まとめ
Angularのデフォルトテストコードはシンプルですが、以下の重要な要素が詰まっています。
- TestBedでテスト環境を構築
- fixtureでコンポーネントを操作
- whenStableで非同期を制御
- expectで結果を検証
Vite + Vitest環境でも基本構造は変わらないため、まずはこのデフォルトコードを正しく理解することが重要です。
次のステップとしては、以下を学ぶと実務レベルに近づきます。
- 入力(@Input)のテスト
- 出力(@Output)のテスト
- サービスのモック化
- 非同期処理のテストパターン
これらを段階的に理解していくことで、Angularのユニットテストを効率的に書けるようになります。
