API · SDK
API クライアントと SDK の設定
ベース URL をコードから切り離して実際のサービスを指すようにし、サンプルのアドレスが本番環境に届かないようチェックを追加します。
ガイド · テスト
api.example-petstore.com のような架空のアドレスを指すコードも、実際のリクエストを送信します。そのリクエストは、その名前を所有している誰かに届きます。Mock API なら、同じ手軽さをそのリスクなしで得られます。自分のマシン上やテストの中で動作し、すぐに応答し、常に期待どおりのデータを返します。
api.example.com のように example.com の下で使われていない名前はまったく名前解決されないため、コードは実際の応答をどう処理するかを示す前に、タイムアウトや DNS エラーで失敗します。Mock API はこの 3 つをすべて解決します。localhost またはテストプロセスの中で待ち受けるので、何もマシンの外に出ません。
| ツール | 向いている用途 | 動作形態 |
|---|---|---|
| Prism | OpenAPI の定義があり、それに従った応答がほしい場合 | ローカルサーバー(Node.js または Docker)、ポート 4010 |
| WireMock | 正確に記録した応答、エラーケース、遅延。言語を問いません | ローカルサーバー(Java または Docker)、ポート 8080 |
| MSW | JavaScript と TypeScript: フロントエンド開発と単体テスト | ブラウザー内、または Node.js のテストプロセス内 |
| json-server | 1 つの JSON ファイルから動く REST API。プロトタイプ向け | ローカルサーバー(Node.js)、ポート 3000 |
Swagger Petstore サンプル API そのものを使う場合は、公式イメージをローカルで実行してください。詳しくは Swagger Petstore をお探しですか?をご覧ください。
Prism は OpenAPI(または Swagger 2.0)の定義を読み込み、そこにあるすべてのオペレーションに、そのファイルの例やスキーマで応答します。定義に合わないリクエストには分かりやすい検証エラーが返るため、本物の API ができる前にクライアントを確認するのに役立ちます。
# Node.js の場合
npm install -g @stoplight/prism-cli
prism mock openapi.yaml
# Docker の場合
docker run --init --rm -v "$(pwd)":/tmp -p 4010:4010 stoplight/prism:5 mock -h 0.0.0.0 /tmp/openapi.yaml
# その後
curl http://127.0.0.1:4010/pets
curl http://127.0.0.1:4010/pets/1 -H "Prefer: code=404"
Prefer ヘッダーを使うと、エラーコードや名前付きの例など、定義の中から特定の応答を選べます。--dynamic(-d)を付けると、Prism はリクエストのたびにスキーマから新しいデータを生成します。
WireMock は、自分で書いたり記録したりしたスタブファイルから応答します。どの言語でも使え、本物のサービスでは狙って起こすことが難しい遅い応答や障害も再現できます。
# mocks/mappings/pet.json
{
"request": { "method": "GET", "url": "/v1/pets/1" },
"response": {
"status": 200,
"headers": { "Content-Type": "application/json" },
"jsonBody": { "id": 1, "name": "Rex", "status": "available" }
}
}
# mappings/ を含むフォルダー(大きなボディ用の __files/ も)を指定して起動
docker run -it --rm -p 8080:8080 -v "$(pwd)/mocks":/home/wiremock wiremock/wiremock
curl http://localhost:8080/v1/pets/1
タイムアウトをテストするには応答に "fixedDelayMilliseconds": 3000 を、再試行をテストするには 503 などのステータスを追加します。/__admin の管理 API を使うと、テストからスタブを追加したり、どのリクエストが届いたかを確認したりできます。
Mock Service Worker は、アプリケーション自体の中でリクエストを横取りします。ブラウザーでは Service Worker を通じて、Node.js ではテストプロセスの中で動作します。テスト対象のコードは通常のベース URL を呼び出し続け、追加のサーバーは動きません。
// handlers.js
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('https://api.example.com/v1/pets/:id', ({ params }) =>
HttpResponse.json({ id: Number(params.id), name: 'Rex', status: 'available' })),
http.post('https://api.example.com/v1/pets', () =>
HttpResponse.json({ error: 'name is required' }, { status: 400 })),
]
// テストの中で(Node.js)
import { setupServer } from 'msw/node'
const server = setupServer(...handlers)
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
onUnhandledRequest: 'error' を指定すると、コードがハンドラーのないアドレスを呼び出した時点でテストが失敗します。そのため、置き忘れたサンプルのアドレスが本番環境ではなくテスト実行の段階で見つかります。ブラウザーでは、npx msw init public/ を一度実行し、msw/browser からワーカーを起動します。
PHP のテストでは、Guzzle の MockHandler がテストプロセスの中で同じ役割を果たします。Symfony には MockHttpClient があります。
// PHP, Guzzle: ネットワークを使わず、順番に応答
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
$mock = new MockHandler([
new Response(200, ['Content-Type' => 'application/json'], '{"id": 1, "name": "Rex", "status": "available"}'),
new Response(400, [], '{"error": "name is required"}'),
]);
$client = new Client(['handler' => HandlerStack::create($mock), 'base_uri' => 'https://api.example.com/v1/']);
// PHP, Symfony
$client = new Symfony\Component\HttpClient\MockHttpClient(
[new Symfony\Component\HttpClient\Response\MockResponse('{"id": 1, "name": "Rex"}')],
'https://api.example.com/v1/'
);
ハンドラー内のアドレスは api.example.com です。これは予約済みの名前なので、リクエストがモックをすり抜けても本物のサーバーには決して届きません。
json-server は、1 つの JSON ファイルを、一覧・詳細・作成・更新・削除のルートを備えた REST API に変えます。変更はファイルに書き戻されるので、プロトタイプやデモに便利です。
# db.json
{
"pets": [ { "id": "1", "name": "Rex", "status": "available" } ],
"orders": []
}
npx json-server db.json
curl http://localhost:3000/pets
curl -X POST http://localhost:3000/orders -H "Content-Type: application/json" -d '{"petId": "1"}'
検証や認証の機能はないため、プロトタイプにとどめてください。契約テストには Prism や WireMock のほうが適しています。
ベース URL は設定に置き、開発とテストではモックを値にして、本物のアドレスはアプリケーションが実際に動く場所だけで使います。
# .env.development
API_BASE_URL=http://localhost:4010
# .env.test
API_BASE_URL=http://localhost:8080
# 本番: ホスティング環境で設定し、リポジトリには決して入れない
API_BASE_URL=https://api.your-real-service.com
サンプルのアドレスが本番環境に届くのを防ぐチェックも含めた詳しい説明は、API クライアントと SDK の設定をご覧ください。