3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オフグリッドAdvent Calendar 2024

Day 9

Jasmine × Karma実践編:モックの活用とカバレッジの完全ガイド

Posted at

はじめに

前回の記事では、JasmineとKarmaを用いた基本的な単体テストの方法を学びました。本記事では、より実践的な内容として、モックを使った依存関係の分離方法と、テストカバレッジの取得・向上方法を解説します。モックを活用することで、外部依存を排除し、テストを効率的に行えるようになります。


目次

  1. モックとは?
  2. モックを活用した単体テストの実践例
  3. 非同期処理のテストとモック
  4. カバレッジの取得方法
  5. カバレッジを向上させるヒント
  6. おすすめのツールとリソース

1. モックとは?

モック(Mock)は、テスト対象が依存するオブジェクトやサービスの代わりに使用する偽の実装です。これにより、依存関係に影響されず、テスト対象の動作を独立して検証できます。

  • なぜモックを使うのか?
    • 外部依存(APIコール、データベースアクセス)を排除できる。
    • 特定の状況を簡単にシミュレートできる。
    • テストが速く、再現性が高くなる。

2. モックを活用した単体テストの実践例

対象サービス

MyServiceがAPIからデータを取得する簡単なサービスを想定します。

@Injectable({
  providedIn: 'root',
})
export class MyService {
  fetchData(): Observable<string[]> {
    return of(['Item 1', 'Item 2', 'Item 3']);
  }
}

モックを利用したテストケース

以下のコードは、MyServiceの依存関係をモックし、コンポーネントのテストを行う例です。

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my-component.component';
import { MyService } from './my-service.service';
import { of } from 'rxjs';

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  let mockService: jasmine.SpyObj<MyService>;

  beforeEach(() => {
    // モックサービスの作成
    mockService = jasmine.createSpyObj('MyService', ['fetchData']);
    mockService.fetchData.and.returnValue(of(['Mock Item 1', 'Mock Item 2']));

    TestBed.configureTestingModule({
      declarations: [MyComponent],
      providers: [
        { provide: MyService, useValue: mockService }, // モックを提供
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should fetch mock data on initialization', () => {
    expect(component.items).toEqual(['Mock Item 1', 'Mock Item 2']);
    expect(mockService.fetchData).toHaveBeenCalled();
  });
});

ポイント解説

  • jasmine.createSpyObj: メソッドを持つモックオブジェクトを生成。
  • and.returnValue: モックメソッドの戻り値を指定。
  • providers: Angularの依存性注入を使い、モックをテスト対象に注入。

3. 非同期処理のテストとモック

対象サービス

API呼び出しを含む非同期処理の例です。

fetchData(): Observable<string[]> {
  return new Observable((observer) => {
    setTimeout(() => {
      observer.next(['Async Item 1', 'Async Item 2']);
      observer.complete();
    }, 1000);
  });
}

非同期処理のテストケース

非同期処理はfakeAsyncまたはasyncを使用してテストします。

it('should handle async data correctly', fakeAsync(() => {
  mockService.fetchData.and.returnValue(
    of(['Async Mock Item 1', 'Async Mock Item 2'])
  );

  component.ngOnInit();
  tick(1000); // 仮想時間を進める
  expect(component.items).toEqual(['Async Mock Item 1', 'Async Mock Item 2']);
}));

4. カバレッジの取得方法

カバレッジレポートの生成

以下のコマンドを実行します:

ng test --code-coverage

**カバレッジレポートの保存場所

テスト実行後、coverageディレクトリにレポートが出力されます。

coverage/
  └── my-angular-app/
      ├── index.html
      ├── ...

カバレッジレポートの確認

  • レポートの内容:
    • Statements: 実行されたコード行の割合。
    • Branches: 条件分岐の網羅率。
    • Functions: 呼び出された関数の割合。

ブラウザでindex.htmlを開き、視覚的に確認できます。


5. カバレッジを向上させるヒント

未カバー部分の特定

カバレッジレポートで「赤く表示」される部分が、未カバーのコードです。これに基づいてテストケースを追加しましょう。

よくある見落としポイント

  • 条件分岐(if, switch)の網羅
  • 例外処理やエラーハンドリングの確認
  • 初期化ロジック(ngOnInitなど)のテスト


おわりに

モックを活用することで、外部依存を切り離し、より効率的かつ信頼性の高い単体テストを実現できます。また、カバレッジレポートを通じてテストの網羅性を評価し、さらなる品質向上に取り組むことが可能です。今回学んだ内容をもとに、あなたのプロジェクトでもテスト環境を強化してみましょう!


3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?