サービスと依存関係のモック
DIでテストダブルを提供します
「サービスと依存関係のモック」はCoddyKit上の無料Angular Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAngular Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Angular Academyコースには全4レッスンが含まれています。
依存関係をモックする理由
コンポーネントテストでは、コンポーネントを分離してテストする必要があります。HttpClient を利用するサービスを注入している場合、実際のネットワーク呼び出しは避けたいものです。代わりに、制御されたデータを返す偽のオブジェクトである テストダブル を提供すると、テストを高速かつ決定的に実行できます。
useValue による偽物の提供
最も単純なテストダブルは、useValue で提供する通常のオブジェクトです。コンポーネントが要求するものと同じインジェクショントークンで提供してください。
const fakeApi = { getUser: () => of({ name: 'Ada' }) };
TestBed.configureTestingModule({
imports: [ProfileComponent],
providers: [{ provide: UserApi, useValue: fakeApi }],
});Jasmine のスパイ
jasmine.createSpyObj はスパイメソッドを持つ偽物を作成します。戻り値をスタブ化すると同時に、呼び出しも検証できます。
const apiSpy = jasmine.createSpyObj<UserApi>('UserApi', ['getUser']);
apiSpy.getUser.and.returnValue(of({ name: 'Ada' }));
TestBed.configureTestingModule({
providers: [{ provide: UserApi, useValue: apiSpy }],
});サービスが呼び出されたことの検証
コンポーネントを操作した後、スパイが期待した引数を受け取ったことを検証します。
fixture.componentInstance.load(7);
fixture.detectChanges();
expect(apiSpy.getUser).toHaveBeenCalledWith(7);
expect(apiSpy.getUser).toHaveBeenCalledTimes(1);モックからの Observable の返却
サービスは Observable を返すことがよくあります。同期的な成功には RxJS の of() を、失敗には throwError() を使い、両方の分岐をテストできるようにします。
import { of, throwError } from 'rxjs';
apiSpy.getUser.and.returnValue(of({ name: 'Ada' })); // success
apiSpy.getUser.and.returnValue(throwError(() => new Error('boom'))); // error再利用可能な偽物のための useClass
多くの spec で偽物を再利用する場合は、クラスを定義し、useClass で接続します。
class FakeUserApi {
getUser() { return of({ name: 'Test' }); }
}
TestBed.configureTestingModule({
providers: [{ provide: UserApi, useClass: FakeUserApi }],
});HttpTestingController による HttpClient のモック
サービス全体を偽装せずにHTTPを呼び出すサービスをテストするには、provideHttpClientTesting()をインポートし、HttpTestingControllerを使ってリクエストをフラッシュします。
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting, HttpTestingController } from '@angular/common/http/testing';
TestBed.configureTestingModule({
providers: [provideHttpClient(), provideHttpClientTesting()],
});HTTPリクエストのフラッシュ
リクエストを期待し、偽のデータで応答してから、予期しない呼び出しが残っていないことを検証します。
const http = TestBed.inject(HttpTestingController);
service.load();
const req = http.expectOne('/api/users/7');
expect(req.request.method).toBe('GET');
req.flush({ name: 'Ada' });
http.verify();テストごとにプロバイダーを上書きする
テストによっては、別の偽物が必要になる場合があります。createComponentを呼び出す前にTestBed.overrideProvider()を使用します。
TestBed.overrideProvider(UserApi, {
useValue: { getUser: () => throwError(() => new Error('fail')) },
});
const fixture = TestBed.createComponent(ProfileComponent);必要な分だけモックする
優れたテストダブルは、コンポーネントが実際に使用するメソッドだけを実装します。過剰なモックはテストを内部実装に依存させ、不十分なモックは実際の副作用を漏れ込ませます。コンポーネントが依存するパブリックな契約に合わせてください。
実際のサービスメソッドをスパイする
実際のサービスをそのまま使いながら、spyOn(instance, 'method')で1つのメソッドだけをスパイすることもできます。サービスの大部分は安全に使えるものの、特定の呼び出しだけをインターセプトする必要がある場合に便利です。
const svc = TestBed.inject(AnalyticsService);
spyOn(svc, 'track');
fixture.componentInstance.onClick();
expect(svc.track).toHaveBeenCalledWith('click');クイックチェック
呼び出しを検証し、戻り値も制御できる偽物を作るにはどうすればよいでしょうか?
まとめ
useValue、useClass、Jasmineのスパイを使って実際の依存関係をテストダブルに置き換え、of/throwErrorでObservableを返し、HttpTestingControllerでHTTPをテストし、テストごとにプロバイダーを上書きしました。コンポーネントが使用する契約だけをモックしてください。
よくある質問
「サービスと依存関係のモック」レッスンは無料ですか?
はい。「サービスと依存関係のモック」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Angular Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Angular Academyコースには全4レッスンが含まれています。
「サービスと依存関係のモック」で何を学びますか?
DIでテストダブルを提供します ブラウザで直接実行するハンズオンコードでAngular Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Angular Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAngular Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「サービスと依存関係のモック」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAngular Academyレッスンでコードを書いて実行できますか?
はい。すべてのAngular Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。