← Angular コース
93. HTTPを使うサービスのテスト — 本物のAPIは呼ばずに検証する
サーバー通信するサービスをテストするとき、本物のAPIを呼ぶのは悪手です。サーバーの状態次第で結果が変わり、遅く、壊れやすいテストになります。そこで providers に provideHttpClientTesting() を登録すると、HttpClient の通信先がテスト用の偽物に差し替わり、実際の通信は一切飛ばなくなります。
検証の主役は HttpTestingController です。サービスのメソッドを呼んだあと、expectOne('/api/users') で「このURLへリクエストが1件飛んだこと」を捕まえ、req.flush(偽データ) で偽のレスポンスを返します。リクエストのメソッドや送信ボディも req.request から検証でき、「正しく呼んでいるか」と「レスポンスを正しく処理するか」の両方を確認できます。
つまずきやすいのは providers の順番と検証漏れです。provideHttpClient() を先に、provideHttpClientTesting() を後に登録する必要があります。また最後に httpTesting.verify() を呼ぶと「想定外のリクエストが残っていないか」まで確認でき、呼び忘れによる見逃しを防げます。
サンプルコード(フレームワーク環境が必要なため表示のみ)
import { TestBed } from '@angular/core/testing';
import { provideHttpClient } from '@angular/common/http';
import {
HttpTestingController,
provideHttpClientTesting,
} from '@angular/common/http/testing';
import { UserService } from './user.service';
it('ユーザー一覧APIを呼んで結果を返す', () => {
TestBed.configureTestingModule({
// 順番が大事: provideHttpClient が先、Testing が後
providers: [provideHttpClient(), provideHttpClientTesting()],
});
const service = TestBed.inject(UserService);
const httpTesting = TestBed.inject(HttpTestingController);
let result: string[] = [];
service.getUsers().subscribe((users) => (result = users));
// 「/api/users へ1件リクエストが飛んだ」ことを捕まえる
const req = httpTesting.expectOne('/api/users');
expect(req.request.method).toBe('GET');
// 偽のレスポンスを返す(本物のサーバーは一切使わない)
req.flush(['テスト太郎', 'テスト花子']);
expect(result).toEqual(['テスト太郎', 'テスト花子']);
// 想定外のリクエストが残っていないか最終確認
httpTesting.verify();
});
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗