【実践編】Angularでテストエラーケースを検証:MarbleテストとJasmine Spy徹底比較
Angularでサービス内のObservablesでテストエラーケースを検証する方法
Angularでサービスを使用する場合、非同期処理を管理するためにObservablesがよく用いられます。しかし、テストにおいて、これらの非同期処理を含むエラーケースを検証するのは難易度が高くなります。
そこで、KarmaとKarma-coverageを利用して、サービス内のObservablesでテストエラーケースを効率的に検証する方法をご紹介します。
ステップ1:KarmaとKarma-coverageのセットアップ
まず、KarmaとKarma-coverageをプロジェクトにインストールする必要があります。
npm install karma karma-coverage --save-dev
// karma.conf.js
module.exports = function(config) {
config.set({
// ... other options
// Karma-coverage configuration
coverageReporter: {
type: 'html',
dir: 'coverage/',
subdir: 'coverage',
reportUrl: 'coverage/report/index.html'
}
});
};
ステップ2:テスト対象のサービスとテストファイルの作成
テスト対象のサービスと、そのサービスを検証するためのテストファイルを作成します。
サービスファイル (example.service.ts)
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ExampleService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get('https://jsonplaceholder.typicode.com/todos/1');
}
}
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ExampleService } from './example.service';
describe('ExampleService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [ExampleService]
});
});
it('should return data from the API', inject([ExampleService], (service: ExampleService) => {
// テスト対象のロジックを検証
}));
it('should handle errors when the API call fails', inject([ExampleService], (service: ExampleService) => {
// エラーケースを検証
}));
});
ステップ3:エラーケースの検証
テストファイルの中で、it
ブロックを使用して、エラーケースを検証します。
例:API呼び出しが失敗した場合の検証
it('should handle errors when the API call fails', inject([ExampleService], (service: ExampleService) => {
// HttpClientTestingModuleを使って、HTTPリクエストをモックします。
const httpMock = TestBed.inject(HttpClient);
httpMock.get.withArgs('https://jsonplaceholder.typicode.com/todos/1').throwError(new Error('API call failed'));
// サービスのgetData()メソッドを呼び出し、エラーハンドリングを検証します。
service.getData().subscribe({
next: (data) => {
fail('エラーが発生していない');
},
error: (error) => {
expect(error.message).toBe('API call failed');
}
});
}));
ステップ4:テストの実行とカバレッジレポートの確認
Karmaを使用して、テストを実行します。
npx karma start
テストが完了したら、Karma-coverageによって生成されたカバレッジレポートを確認できます。このレポートには、テスト対象のコードがどの程度カバレッジされているかが表示されます。
KarmaとKarma-coverageを利用することで、Angularサービス内のObservablesでテストエラーケースを効率的に検証することができます。この方法を活用することで、より信頼性の高いサービスを開発することができます。
- KarmaとKarma-coverage以外にも、テストエラーケースを検証するためのツールは多数存在します。
- テスト対象のサービスやテストケースの複雑さに応じて、適切な検証方法を選択することが重要です。
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ExampleService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get('https://jsonplaceholder.typicode.com/todos/1');
}
}
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ExampleService } from './example.service';
describe('ExampleService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [ExampleService]
});
});
it('should return data from the API', inject([ExampleService], (service: ExampleService) => {
// 成功時のテストロジック
service.getData().subscribe({
next: (data) => {
// レスポンスデータを検証
expect(data.id).toBe(1);
expect(data.title).toBe('Lorem ipsum');
},
error: (error) => {
fail('予期せぬエラーが発生しました');
}
});
}));
it('should handle errors when the API call fails', inject([ExampleService], (service: ExampleService) => {
// エラーケースのテストロジック
const httpMock = TestBed.inject(HttpClient);
httpMock.get.withArgs('https://jsonplaceholder.typicode.com/todos/1').throwError(new Error('API call failed'));
service.getData().subscribe({
next: (data) => {
fail('エラーが発生していない');
},
error: (error) => {
// エラーメッセージを検証
expect(error.message).toBe('API call failed');
}
});
}));
});
このテストファイルには、2つのit
ブロックがあります。
- 1つ目のブロックは、API呼び出しが成功した場合のテストロジックを記述しています。
ポイント
HttpClientTestingModule
を利用することで、HTTPリクエストをモックすることができます。subscribe
メソッドを使用して、Observablesの値とエラーを購読することができます。expect
アサーションを使用して、テスト結果を検証することができます。
メリット
- テスト対象のObservablesの内部構造を理解する必要がない
- 複雑な非同期処理をテストしやすい
- KarmaとKarma-coverageよりも設定が複雑
- Marbleの使用方法を学ぶ必要がある
例
import { cold, hot } from 'marble-test';
import { ExampleService } from './example.service';
describe('ExampleService', () => {
it('should return data from the API', () => {
const service = new ExampleService();
const expectedResponse = { id: 1, title: 'Lorem ipsum' };
const expected$ = cold('(v|)', { v: expectedResponse });
const actual$ = service.getData();
expect(actual$).toBeObservable(expected$);
});
it('should handle errors when the API call fails', () => {
const service = new ExampleService();
const expectedError = new Error('API call failed');
const expected$ = hot('-(e|)', { e: expectedError });
const actual$ = service.getData();
expect(actual$).toBeObservable(expected$);
});
});
Jasmine Spy
Jasmine Spyは、テスト対象のコードをモックするために使用できるJasmine機能です。Jasmine Spyを利用することで、サービス内のObservablesをモックし、テストケースでどのように振る舞うかを検証することができます。
- テスト対象のコードをモックしやすい
- 複雑な非同期処理をテストするのは難しい
- テスト対象のコードを理解する必要がある
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ExampleService } from './example.service';
import { of, throwError } from 'rxjs';
describe('ExampleService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [ExampleService]
});
});
it('should return data from the API', inject([ExampleService], (service: ExampleService) => {
const spy = spyOn(service, 'getData').and.returnValue(of({ id: 1, title: 'Lorem ipsum' }));
service.getData().subscribe({
next: (data) => {
// レスポンスデータを検証
expect(data.id).toBe(1);
expect(data.title).toBe('Lorem ipsum');
},
error: (error) => {
fail('予期せぬエラーが発生しました');
}
});
expect(spy).toHaveBeenCalled();
}));
it('should handle errors when the API call fails', inject([ExampleService], (service: ExampleService) => {
const spy = spyOn(service, 'getData').and.returnValue(throwError(new Error('API call failed')));
service.getData().subscribe({
next: (data) => {
fail('エラーが発生していない');
},
error: (error) => {
// エラーメッセージを検証
expect(error.message).toBe('API call failed');
}
});
expect(spy).toHaveBeenCalled();
}));
});
Mock Service
Mock Serviceは、テスト対象のサービスをモックしたクラスです。Mock Serviceを利用することで、サービス内のObservablesをモックし、テストケースでどのように振る舞うかを検証することができます。
- Mock Serviceを作成する必要がある
import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class MockExampleService {
getData(): Observable<any> {
return of({
angular typescript karma-coverage