← 解説「コンポーネントのテスト — TestBedで部品を組み立てて表示を検証」に戻る
サンプルコードで身につける: コンポーネントのテスト — TestBedで部品を組み立てて表示を検証
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1コンポーネントテストの基本形
組み立て、描画、検証の3ステップが基本形です。standalone コンポーネントは imports に登録し、createComponent で生成、detectChanges で描画してから DOM を確認します。この形をまず型として覚えましょう。
import { TestBed } from '@angular/core/testing';
import { Header } from './header';
it('タイトルが表示される', () => {
// 1. 組み立て: standalone コンポーネントは imports に入れる
TestBed.configureTestingModule({ imports: [Header] });
const fixture = TestBed.createComponent(Header);
// 2. 描画: これを呼ぶまでDOMは空
fixture.detectChanges();
// 3. 検証: 実際のDOMを取り出して文言を確かめる
const el: HTMLElement = fixture.nativeElement;
expect(el.querySelector('h1')?.textContent).toContain('マイアプリ');
});
2setInput で Input を流し込む
input() で定義した Input には fixture.componentRef.setInput で値を渡せます。値を変えたら detectChanges を呼び直すことで、Input の変化に応じた表示の切り替わりを検証できます。
// user-badge.ts(テスト対象)
// export class UserBadge {
// name = input.required<string>();
// isAdmin = input(false);
// }
it('管理者には[管理者]バッジが付く', () => {
TestBed.configureTestingModule({ imports: [UserBadge] });
const fixture = TestBed.createComponent(UserBadge);
// Input を外から流し込む(親コンポーネントは不要)
fixture.componentRef.setInput('name', '佐藤');
fixture.componentRef.setInput('isAdmin', true);
fixture.detectChanges();
const el: HTMLElement = fixture.nativeElement;
expect(el.textContent).toContain('佐藤');
expect(el.textContent).toContain('管理者');
});
3ボタンクリックで表示が変わることを検証する
nativeElement から取得したボタンの click() を呼べば、ユーザーの操作を再現できます。操作のあとに detectChanges を呼び、変化後の表示を検証する流れです。
// counter.ts(テスト対象)
// export class Counter {
// count = signal(0);
// increment() { this.count.update((c) => c + 1); }
// }
it('ボタンを押すとカウントが増える', () => {
TestBed.configureTestingModule({ imports: [Counter] });
const fixture = TestBed.createComponent(Counter);
fixture.detectChanges();
const el: HTMLElement = fixture.nativeElement;
// ユーザーの操作を再現: ボタンをクリック
el.querySelector('button')?.click();
// 操作後は再描画してから検証する
fixture.detectChanges();
expect(el.textContent).toContain('カウント: 1');
});
4リスト表示の件数を検証する
@for で並べたリストは querySelectorAll で要素を数えて検証します。0件のときに空メッセージが出るか、といった分岐の確認も同じ道具立てでできます。
it('渡した商品の数だけ行が表示される', () => {
TestBed.configureTestingModule({ imports: [ProductList] });
const fixture = TestBed.createComponent(ProductList);
fixture.componentRef.setInput('products', [
{ name: 'りんご', price: 100 },
{ name: 'みかん', price: 80 },
]);
fixture.detectChanges();
const el: HTMLElement = fixture.nativeElement;
// @for で描画された行の数を数える
expect(el.querySelectorAll('li').length).toBe(2);
});
it('0件のときは空メッセージが出る(境界値は画面でも試す)', () => {
TestBed.configureTestingModule({ imports: [ProductList] });
const fixture = TestBed.createComponent(ProductList);
fixture.componentRef.setInput('products', []);
fixture.detectChanges();
const el: HTMLElement = fixture.nativeElement;
expect(el.textContent).toContain('商品がありません');
});
5detectChanges を忘れるとどうなるか
createComponent した直後の DOM は空で、setInput しただけでは画面に反映されません。detectChanges の呼び忘れは初学者が最初に踏む落とし穴なので、失敗する形を一度見ておきましょう。
it('detectChanges を忘れた例(これは失敗する)', () => {
TestBed.configureTestingModule({ imports: [Header] });
const fixture = TestBed.createComponent(Header);
const el: HTMLElement = fixture.nativeElement;
// detectChanges() を呼んでいないので、DOMはまだ空っぽ
// expect(el.querySelector('h1')?.textContent).toContain('マイアプリ');
// → Expected: 'マイアプリ' / Received: undefined で失敗
});
// 覚え方:
// ・createComponent した直後 → まず detectChanges()
// ・setInput やクリックで状態を変えた後 → もう一度 detectChanges()
// 「表示が変わらない」と思ったら、まずこれを疑う