スポンサーリンク

Angular ユニットテストの基本(Vitest対応)|デフォルトコードの意味を完全解説

この記事は「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のユニットテストを効率的に書けるようになります。