Webhookをテストするには、プロバイダーから到達できるURLを用意し、実際のイベントを発生させ、ハンドラーがペイロードを受信・検証・処理できることを確認します。通常のAPIのように「送信」してレスポンスを見るだけでは不十分です。Webhookではアプリケーションがリクエストの受信側になるため、キャプチャ、ローカルトンネル、プロバイダーのテストイベント、アサーションを組み合わせてエンドツーエンドで検証します。
Webhookが通常のAPIよりテストしにくい理由
通常のAPIテストでは、クライアント側でメソッド、ヘッダー、ボディ、実行タイミングを制御できます。一方、Webhookではプロバイダーがイベント発生時にリクエストを送信します。この違いにより、テストでは次の点を考慮する必要があります。
イベントを自分で直接発生させにくい
例えばpayment_intent.succeededは、Stripe側で支払い成功イベントが作成されたときに送信されます。再現にはプロバイダーのCLIや管理画面が必要です。配信が非同期である
テストコードが戻り値を待つのではなく、外部から届くリクエストを待ち受けて検証します。ペイロード形式はプロバイダーが決める
GitHub、Stripe、Slackなど、それぞれのイベント形式に合わせてパースする必要があります。署名検証が必要になる
多くのプロバイダーはWebhookリクエストに署名ヘッダーを付与します。ハンドラーはボディを信頼する前に署名を検証する必要があります。詳細はWebhook署名検証を参照してください。
Webhookを採用すべきか検討中の場合は、Webhooks vs PollingとWebhook vs WebSocketで比較できます。
Webhookテストに必要なツール
Webhookテストでは、主に次の4種類のツールを使います。
- 実際のリクエストを確認するキャプチャサービス
-
localhostを外部公開するトンネル - 実際のイベントを発生させるプロバイダーのテスト機能
- ハンドラーのレスポンスや副作用を検証するテストツール
1. キャプチャサービスで実際のペイロードを確認する
ハンドラーを書く前に、まずプロバイダーが実際に何を送ってくるか確認します。使い捨ての公開URLにWebhookを向けると、メソッド、ヘッダー、ボディをそのまま確認できます。
webhook.site
webhook.site はページを開くと一意のURLを発行し、そこに送信されたHTTPリクエストをリアルタイムで表示します。
確認できる内容は次のとおりです。
- HTTPメソッド
- ヘッダー
- リクエストボディ
- クエリパラメータ
- 送信時刻
無料URLは7日後に期限切れになり、100リクエストまで、最大リクエストサイズは10MBです。有料プランでは永続URL、無制限リクエスト、最新10,000件の履歴などが利用できます。
Beeceptor
Beeceptor は無料のHTTPSエンドポイントを作成でき、Webhookレシーバーとして使えます。受信ペイロードの確認に加えて、モックサーバーとしても使えるため、キャプチャとシミュレーションを同じツールで行えます。
Pipedream RequestBin
Pipedream RequestBin もWebhookやHTTPリクエストのキャプチャによく使われます。無料枠や制限は変更されることがあるため、利用前に公式ドキュメントを確認してください。
実施手順
- キャプチャサービスで一時URLを作成する
- プロバイダーのWebhook設定にそのURLを登録する
- テストイベントを発生させる
- 受信したヘッダーとボディを保存する
- 後続のテスト用サンプルとして利用する
2. トンネルでlocalhostを公開する
プロバイダーはローカルマシンの localhost:3000 に直接アクセスできません。ローカルでWebhookハンドラーをデバッグするには、トンネルツールで公開HTTPS URLを作成し、そこからローカルポートへ転送します。
ngrokを使う
brew install ngrok
ngrok config add-authtoken $YOUR_TOKEN
ngrok http 3000
ngrok http 3000 を実行すると、次のような公開URLが発行されます。
https://xxxx-xx-xx-xx-xx.ngrok-free.app
プロバイダーのWebhook URLには、ローカルのパスを含めて登録します。
https://xxxx-xx-xx-xx-xx.ngrok-free.app/webhooks
無料のngrokアカウントでは自動生成された開発ドメインを利用できます。カスタムドメインを使う場合は有料プランが必要です。
cloudflaredを使う
Cloudflareを使う場合は、cloudflared でクイックトンネルを作成できます。
cloudflared tunnel --url http://localhost:3000
出力された公開URLをWebhook設定に登録すると、外部からのイベントがローカルサーバーに届きます。
localhost APIをWebhookサービスからテストする流れは、Webhookサービスでlocalhost APIをテストする方法でも解説しています。
3. プロバイダーからテストイベントを発生させる
キャプチャURLやトンネルURLを用意しても、イベントが送信されなければテストできません。主要なプロバイダーは、テストイベントを発生させるCLIや管理画面を提供しています。
Stripe CLIでテストする
Stripeでは stripe listen でイベントをローカルハンドラーに転送できます。
stripe listen --forward-to localhost:3000/webhooks
特定のイベントだけを転送する場合は --events を指定します。
stripe listen --events payment_intent.succeeded,checkout.session.completed \
--forward-to localhost:3000/webhooks
stripe listen を実行すると、Webhook署名検証に使うシークレットも出力されます。アプリケーション側の環境変数などに設定してください。
イベントを発生させるには stripe trigger を使います。
stripe trigger payment_intent.succeeded
stripe trigger checkout.session.completed
stripe trigger --help
注意点として、トリガーは関連するAPIオブジェクトを作成し、副次的なイベントも発生させる場合があります。例えば payment_intent.succeeded により payment_intent.created も発生することがあります。
GitHub Webhookを再配信する
GitHubでは、最近のWebhook配信を管理画面から再配信できます。
手順は次のとおりです。
- 対象リポジトリを開く
-
Settingsを開く -
Code and automation配下のWebhooksを開く - 対象Webhook URLをクリックする
-
Recent Deliveriesタブを開く - 配信GUIDをクリックする
-
Redeliverをクリックする
制約は次の2つです。
- 再配信できるのは過去3日間の配信のみ
- リポジトリへの管理者権限が必要
GitHubは失敗した配信を自動で再配信しないため、再送は手動で行います。
Slack Incoming Webhookをテストする
SlackのIncoming Webhookは、Webhook URLにJSONをPOSTするだけでテストできます。
curl -X POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX \
-H 'Content-type: application/json' \
-d '{"text":"Hello, world."}'
最小ペイロードは text フィールドのみです。
{
"text": "Hello, world."
}
SlackのWebhook URLは秘密情報です。クライアントサイドコードや公開リポジトリに含めないでください。漏洩したURLはSlackによって取り消される場合があります。
4. ハンドラーを検証する
キャプチャやトンネルは「イベントが届く」ことを確認するためのものです。ハンドラーが正しく処理しているかは、別途検証する必要があります。
最小限のスモークテストは curl で実行できます。
curl -X POST http://localhost:3000/webhooks \
-H 'Content-Type: application/json' \
-H 'Stripe-Signature: t=...,v1=...' \
-d '{"id":"evt_test","type":"payment_intent.succeeded","data":{"object":{"id":"pi_123","status":"succeeded"}}}'
ただし、これだけではCIで繰り返し実行できるテストとしては不十分です。以下を検証対象に含める必要があります。
- ステータスコード
- レスポンスボディ
- 署名検証の成功・失敗
- DBへの保存結果
- ダウンストリームAPI呼び出し
- 冪等性
- 不正ペイロードの拒否
Apidogを使ってWebhookテストを実装する
Apidog は、APIの設計、デバッグ、テスト、モック、ドキュメント作成を行うAPIプラットフォームです。専用の「Webhook受信トレイ」はありませんが、キャプチャ済みペイロードを再利用可能なリクエストとして保存し、レスポンスを検証し、モックサーバーで外部プロバイダーの代替を作る用途に使えます。
サンプルペイロードを保存する
まず、webhook.site などで取得した実際のペイロードをApidogに登録します。
手順は次のとおりです。
- Apidogで対象APIまたはリクエストを作成する
- メソッドを
POSTにする - URLをローカルまたはトンネルURLに設定する
-
Content-Type: application/jsonを追加する - プロバイダーが送信する署名ヘッダーを追加する
- キャプチャしたJSONボディを貼り付ける
- リクエストを保存する
例:
POST http://localhost:3000/webhooks
Content-Type: application/json
Stripe-Signature: t=...,v1=...
{
"id": "evt_test",
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_123",
"status": "succeeded"
}
}
}
これにより、毎回 curl を書き直さずに、同じペイロードを繰り返し送信できます。
アサーションでレスポンスを検証する
Webhookハンドラーは、単に 200 を返せばよいわけではありません。期待したレスポンスや処理結果になっているかを確認します。
Apidogでは、リクエストまたはシナリオステップで次のようにアサーションを追加できます。
-
Post Processorsを開く -
+ Addをクリックする -
Assertionを選択する - 検証対象をレスポンスボディまたはステータスコードに設定する
- 条件を指定する
例えば、レスポンスボディの data.status が succeeded であることを確認する場合は、JSONPathで次のように指定します。
$.data.status
条件は Equals、期待値は次のようにします。
succeeded
これにより、テストは次のような単純な確認から、
ステータスコードが200である
次のような具体的な検証に変わります。
ステータスコードが200であり、data.status が succeeded であり、注文IDが一致する
型を厳密に検証したい場合、例えば数値や真偽値をチェックしたい場合は、Postman互換の pm.test 構文を使ったカスタムスクリプトに切り替えます。
不正系もシナリオに含める
Webhookでは正常系だけでなく、不正なリクエストの拒否も重要です。次のケースを別リクエストまたはシナリオとして保存しておくと、回帰テストに使えます。
- 有効な署名
- 無効な署名
- 署名ヘッダーなし
- 必須フィールドなし
- 未対応イベントタイプ
- 同じイベントIDの再送
- 不正なJSON
- 期限切れタイムスタンプ
例:
{
"id": "evt_duplicate",
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_123",
"status": "succeeded"
}
}
}
同じ id を複数回送信し、2回目以降が冪等に処理されるか確認します。
Apidogのモックサーバーをプロバイダーの代替にする
Webhookハンドラーの受信テストとは別に、自分のサービスが外部プロバイダーAPIを呼び出すケースもあります。その場合、ローカルテスト中に実際のプロバイダーへアクセスせず、Apidogのモックサーバーを使って応答を固定できます。
Apidogには次のモックがあります。
ローカルモック
デスクトップクライアント上で動作し、クライアント起動中のみ利用できます。クラウドモック
Apidogサーバー上でホストされ、24時間利用できます。オン・オフを切り替えられ、デフォルトはオフです。ランナーモック
自己ホスト型のランナー環境で動作し、チーム内で共有できます。
各HTTPエンドポイントにはモックモジュールがあり、デザインモードのAPIタブまたはデバッグモードのモックタブからモックURLをコピーできます。
注意点として、/ で始まるパスのみがモック環境にルーティングされます。
テスト対象コードの外部APIベースURLをモックURLに差し替えることで、実APIへの呼び出しや副作用を避けながら、安定したテストを実行できます。
Apidog CLIでCI実行する
ローカルでシナリオが通ったら、Apidog CLIでCIに組み込みます。Node.js v16以降が必要です。
npm install -g apidog-cli
node -v && apidog -v && which node && which npm && which apidog
保存済みシナリオを実行するには、ApidogのCI/CD Command line タブからアクセストークンやIDを取得し、次のように実行します。
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 637132 -e 358171 -d 3497013 -r html,cli
主なオプションは次のとおりです。
| オプション | 内容 |
|---|---|
-t |
テストシナリオID |
-e |
環境ID。必須 |
-d |
テストデータ。CSV/JSONファイルパス、または保存済みデータセットID |
-r |
レポーター。cli、html、json、junit を指定可能 |
詳細はApidog CLIチュートリアルを参照してください。
Webhookテストを視覚的に作成して検証したい場合は、Apidogを無料でお試しください。クレジットカードは不要です。
Webhookテストの実装ワークフロー
実際の開発では、次の順序で進めると再現性のあるテストを作れます。
実際のペイロードをキャプチャする
プロバイダーのWebhook URLをwebhook.siteなどに向け、実イベントを1つ発生させます。ボディ、ヘッダー、署名形式を保存します。ローカルハンドラーに到達させる
アプリをローカルで起動し、ngrok http 3000またはcloudflared tunnel --url http://localhost:3000で公開します。プロバイダー設定を更新する
発行されたHTTPS URLに/webhooksなどのパスを付けて、プロバイダーのWebhook設定に登録します。本物のイベントを送信する
Stripe CLI、GitHubのRedeliver、SlackへのPOSTなどを使い、トンネル経由でハンドラーにイベントを届けます。署名検証をテストする
有効な署名では受け入れ、改ざんされた署名では拒否されることを確認します。レスポンスを検証する
ステータスコードだけでなく、レスポンスボディ、エラーメッセージ、処理結果を確認します。副作用を検証する
DB更新、ジョブ投入、外部API呼び出し、通知送信など、期待される処理が行われたか確認します。冪等性を確認する
同じイベントIDを複数回送信し、重複処理されないことを確認します。Apidogに保存する
正常系、不正系、再送系のペイロードをリクエストまたはシナリオとして保存します。CIで実行する
Apidog CLIを使い、プッシュやプルリクエストごとにWebhookシナリオを実行します。
Webhookシステムを設計する立場の場合は、信頼性の高いWebhookを設計する方法と支払いWebhookのベストプラクティスも参考になります。再試行、冪等性、セキュリティを考慮する必要があります。
より広い設計観点では、Webhook APIガイドとWebhookとイベント駆動型アーキテクチャで、Webhookがシステム全体にどう組み込まれるかを確認できます。
よくある質問
Webhookをテストするにはどうすればよいですか?
プロバイダーが到達できるURLを用意し、実イベントまたはテストイベントを発生させます。その後、ハンドラーがペイロードを受信し、署名を検証し、正しいステータスを返し、期待される副作用を実行することを確認します。最初に実際のペイロードをキャプチャし、それを再利用可能なテストリクエストとして保存すると安定します。
ローカルでWebhookをテストするにはどうすればよいですか?
ローカルサーバーを起動し、ngrok http 3000 または cloudflared tunnel --url http://localhost:3000 で公開HTTPS URLを作成します。そのURLをプロバイダーのWebhook設定に登録し、イベントを発生させます。受信リクエストはローカルサーバーに届くため、ブレークポイントを設定してデバッグできます。
PostmanでWebhookをテストするにはどうすればよいですか?
Postmanは作成済みペイロードをWebhookエンドポイントにPOSTし、レスポンスを検証できます。ただし、それ単体で実際の受信Webhookを待ち受ける用途には向きません。Apidogでも同様に、プロバイダーのペイロードとヘッダーを使ったリクエストを作成し、レスポンスに検証を追加して再利用可能なテストとして保存できます。本物の受信イベントを確認するには、キャプチャサービスまたはトンネルと組み合わせます。
Stripe Webhookをテストするにはどうすればよいですか?
Stripe CLIを使います。
stripe listen --forward-to localhost:3000/webhooks
このコマンドでサンドボックスイベントをローカルハンドラーへ転送し、署名シークレットを取得します。その後、次のようにイベントを発生させます。
stripe trigger payment_intent.succeeded
対応イベントは次のコマンドで確認できます。
stripe trigger --help
トリガーは関連するAPIオブジェクトを作成し、連鎖的なイベントを発生させることがあります。
Slack Webhookをテストするにはどうすればよいですか?
Incoming Webhook URLにJSONをPOSTします。
curl -X POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX \
-H 'Content-type: application/json' \
-d '{"text":"Hello, world."}'
成功すると、設定済みのSlackチャンネルにメッセージが投稿されます。Webhook URLは秘密情報として扱い、公開リポジトリやクライアントサイドコードに含めないでください。
Webhook URLをテストするにはどうすればよいですか?
代表的なペイロードを POST し、成功ステータスを返すか確認します。最小限の確認には curl が使えます。ただし実運用に近いテストでは、実際のペイロードをキャプチャし、有効な署名と無効な署名の両方で送信し、レスポンスと副作用まで検証してください。
Top comments (0)