0Pricing
Angular Academy · レッスン

サービスと依存関係のモック

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. TestBedとコンポーネントフィクスチャ
  2. Inputs、Outputs、DOMのテスト
  3. サービスと依存関係のモック
  4. Signalsと非同期コードのテスト
← Angular Academyに戻る