スポンサーリンク

Angular × Vitest サービス依存があるコンポーネントテストでモックする方法

この記事は「Angular × Vite ユニットテスト入門|Vitestで始めるテスト完全ガイド」シリーズの一部です。

Angularでサービス依存があるコンポーネントのテストとは

Angularのコンポーネントは、サービス(Service)に依存しているケースが一般的です。
そのため、コンポーネント単体の見た目だけでなく、サービスとの連携も含めてテストする必要があります。

しかし、実際のサービスをそのまま使うと次のような問題が発生します。

  • API通信など外部依存が混ざる
  • テストが不安定になる
  • 実行速度が遅くなる

この問題を解決するために、テストではモック(テストダブル)を使います。

前提:テスト対象のサンプルコンポーネント

サービスに依存しているコンポーネントの例です。

import { Component, inject } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-user',
  template: `<p>{{ message }}</p>`
})
export class UserComponent {
  private userService = inject(UserService);

  message = "デフォルトメッセージ"

  login() {
    this.message = this.userService.isLoggedIn()
    ? 'ログイン済み'
    : '未ログイン';
  }

}

なぜ実サービスを使わないのか

実サービスを使うと、以下のようなリスクがあります。

  • 外部環境に依存する
  • テスト結果が不安定になる
  • 再現性が低くなる

そのため、Angularのテストではモックやスタブを使用するのが基本です。

Vitest対応:モックサービスの作り方

Vitestでは vi.fn() を使って簡単にモックを作成できます。

import { vi } from 'vitest';

class MockUserService {
isLoggedIn = vi.fn(() => true);
}

このようにすることで、テストごとに挙動を変更できます。

TestBedでモックを注入する

Angularでは TestBed を使って依存性を差し替えます。

class MockUserService {
  isLoggedIn = vi.fn(() => true);
}

describe('UserComponent', () => {
  let fixture: ComponentFixture<UserComponent>;
  let component: UserComponent; 

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [UserComponent],
      providers: [
        { provide: UserService, useClass: MockUserService }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(UserComponent);
    component = fixture.componentInstance;
  });

  it('ログイン済みメッセージが表示される', () => {
    component.login();
    fixture.detectChanges();

    const el = fixture.nativeElement;
    expect(el.textContent).toContain('ログイン済み');
  });


});

モックの挙動をテストごとに変える

モックの大きなメリットは、テストケースごとに動作を変更できることです。
mockReturnValue をつかうことで、戻り値を変更することができます。

  it('未ログインの場合', () => {
    const service = TestBed.inject(UserService) as MockUserService;
    service.isLoggedIn.mockReturnValue(false);
    component.login();

    fixture.detectChanges();

    const el = fixture.nativeElement;
    expect(el.textContent).toContain('未ログイン');
  });

まとめ

Angularでサービス依存があるコンポーネントをテストする際は、以下が重要です。

  • サービスはモック化する
  • TestBedで依存性を差し替える
  • Vitestではvi.fnを使う

これらを押さえることで、安定したコンポーネントテストを実装できます。