Smart mock(スマートモック)を使えば、数秒でフェイクAPIを作成できます。エンドポイントのスキーマを読み取り、もっともらしいデータ、つまり本物のようなメールアドレス、意味のあるタイムスタンプ、`xJ8kQ`ではない名前などを返します。ほとんどのフロントエンド開発作業では、これだけで十分な足かせが取り除かれます。
しかし、Smart mockでは対応できないケースに遭遇することがあります。たとえば、`/login`が既知のユーザーに対しては`200`を返し、それ以外では`401`を返すようにしたい場合。あるいは、`/orders/{id}`があるIDに対しては発送済み注文を返し、別のIDに対してはキャンセル済み注文を返すようにしたい場合。また、エラーハンドリングを本番環境に投入する前にテストするために、オンデマンドで`500`エラーを強制したい場合などです。Smart mockはエンドポイントごとに1つのレスポンス形状しか返さないため、リクエストに応じて分岐することはできません。このガイドでは、そのギャップを埋める方法を説明します。
Apidogは、ルールベースの条件付きレスポンスを実現するモック期待値と、ルールでは表現できないロジックに対応するモックスクリプトという2つの機能でこれをカバーします。このウォークスルーでは、具体的な例を交えながら両方を紹介し、カスタムルールがSmart mockよりも常に優先されるように、その優先順位について説明します。基本が初めての方は、APIモックの概要が良い準備になります。そして、Apidogは今回使用するツールです。OpenAPI Initiativeは、これらすべてを可能にする契約ファーストのワークフローを文書化しています。
条件付きモックの本当の意味
条件付きモックとは、ルールです。つまり、着信リクエストが*これ*のようであれば、*あれ*を返すというものです。Apidogは、このルールを2つのレイヤーで構築します。
最初のレイヤーは、エンドポイントスキーマ内でのフィールドレベルのカスタマイズです。フィールドを固定値に設定したり、動的なFaker.js式をアタッチして、呼び出しごとに値が変わるようにしたりします。これは*フィールドが含む内容*を制御しますが、エンドポイントに対しては依然として1つのレスポンス形状を返します。
2番目のレイヤーは、フルレスポンスのモック期待値です。期待値とは、オプションの条件と、それ自身のレスポンスボディ、ステータスコード、ヘッダーを持つ名前付きルールです。条件のない期待値は、無条件に固定データを返します。条件のある期待値は、リクエストが一致した場合にのみデータを返します。これらをいくつか重ねることで、真の分岐を実現できます。たとえば、リクエストが条件Aに一致した場合はレスポンスBを返し、ヘッダーがない場合はエラーボディを返し、パスパラメータごとに異なるペイロードを返すといった具合です。
この2番目のレイヤーによって、オンデマンドのエラーステートとリクエストごとのボディが可能になります。このガイドの残りの部分は、この機能に焦点を当てています。
まず、フィールドレベルの動的値
分岐の前に、単一のフィールドがどのように値を取得するかを確認しておくと役立ちます。なぜなら、条件付きレスポンスでも同じ構文を再利用するからです。
エンドポイントのスキーマ内では、任意の文字列フィールドに`{{$category.method}}`として記述されたFaker.js式を含めることができます。Apidogは、モック呼び出しごとに、JSON Schema定義で既に宣言されているフィールドタイプを使用して、この式を新たに解決します。
{
"id": "{{$number.int(min=1000,max=9999)}}",
"customer": "{{$person.fullName}}",
"email": "{{$internet.email}}",
"product": "{{$commerce.productName}}",
"shippingAddress": "{{$location.streetAddress}}, {{$location.city}}",
"orderedAt": "{{$date.between(from='2024-01-01',to='2024-12-31',format='yyyy-MM-dd')}}"
}
パラメータ付きメソッドも機能するため、`{{$number.int(min=1000,max=9999)}}`は値を制限し、`{{$date.between(...)}}`は範囲と形式を固定します。静的なテキストと複数の式を1つのフィールド内で連結することもできます。上記の住所がこのように構築されるのはそのためです。地域固有のデータが必要な場合は、Apidogはカスタマイズ可能なモックロケールをサポートしており、名前、住所、電話番号を特定の言語や国に合わせることができます。ApidogのFaker.jsリファレンスには、すべてのメソッドカタログが記載されています。

これはSmart mockの領域です。動的ではありますが、条件付きではありません。リクエストに基づいて分岐するには、期待値に移行します。
ウォークスルー:200または401を返すログインエンドポイント
典型的なケース:`POST /login`は、`username`と`password`を含むJSONボディを受け取ります。既知のユーザーはトークンとともに`200`を受け取るべきであり、それ以外のユーザーは`401`を受け取るべきです。
適切なタブを開く
これを設定する場所は、作業モードによって異なります。
- DEBUG (Request-first) モードでは、エンドポイントを開き、**Mock**タブをクリックします。

- DESIGN (Design-first) モードでは、エンドポイントを開き、**Advanced mock**タブをクリックします。

どちらも同じ期待値リストに繋がります。もし一緒に試してみたいけれど、まだアプリをお持ちでない場合は、Apidogをダウンロードして、まず`/login`エンドポイントをインポートまたは作成してください。
成功期待値を追加する
**New expectation**をクリックします。`login-success`のような**期待値名**を付けます。次に条件を追加します。`username`はJSONリクエストボディ内にあるため、ボディパラメータとして一致させます。ターゲットプロパティ`username`のJSONパスを名前フィールドに入れ、条件を`alice@example.com`と等しくなるように設定します。

ボディパラメータの条件はJSONのみであり、名前フィールドのJSONパスを介して一致します。そのため、ネストされたプロパティは`user.email`のようなドットパスを使用します。**Response data**に成功ペイロードを入力します。
{
"token": "mock-jwt-{{$string.uuid}}",
"user": {
"id": 4821,
"username": "alice@example.com",
"role": "member"
}
}
保存します。デフォルトの**HTTPステータスコード**は`200`なので、ハッピーパスの場合は他に何も触る必要はありません。
失敗期待値を追加する
再度**New expectation**をクリックします。`login-failure`と名付け、条件は空のままにしてキャッチオールとして機能させます。**Response data**をエラーボディに設定します。
{
"error": "invalid_credentials",
"message": "Username or password is incorrect."
}
これはデフォルト以外のステータスが必要です。期待値の**More**タブを開き、**HTTPステータスコード**を`401`に設定します。このタブでは、ミリ秒単位の**レスポンス遅延**(デフォルトは`0`)やカスタムレスポンスヘッダーも設定できることに注意してください。400ミリ秒の遅延は、ローディングスピナーが実際にレンダリングされることを確認する手軽な方法です。
順序が重要
期待値は上から下へと評価され、最初に一致したものが優先されます。したがって、`login-success`は`login-failure`の*上*に配置する必要があります。`username`が`alice@example.com`であるリクエストは最初のルールに一致し、トークンを返します。それ以外のリクエストは無条件の失敗ルールにフォールバックし、`401`を受け取ります。もし順序を逆にした場合、条件なしのルールがすべてに一致してしまい、成功ケースが実行されることはありません。
エンドポイントから**モックURL**をコピーし、両方のパスをテストします。
# 既知のユーザー -> トークン付きで200
curl -X POST https://<your-mock-host>/login \
-H "Content-Type: application/json" \
-d '{"username":"alice@example.com","password":"whatever"}'
# その他のユーザー -> 401
curl -X POST https://<your-mock-host>/login \
-H "Content-Type: application/json" \
-d '{"username":"stranger@example.com","password":"whatever"}'
ウォークスルー:ステータスに応じた/orders/{id}の異なるボディ
2番目の一般的なケースは、パスパラメータに基づいた分岐です。`/orders/{id}`が、あるIDに対しては発送済み注文を返し、別のIDに対してはキャンセル済み注文を返すようにして、ライブバックエンドなしでUIがすべての状態をレンダリングできるようにしたい場合です。
ステートごとに1つの期待値を作成します。それぞれについて、パスパラメータ`id`に条件を追加し、一致する**Response data**を入力します。
期待値`order-shipped`、条件:パスパラメータ`id`が`5001`と等しい。
{
"id": 5001,
"status": "shipped",
"total": 129.90,
"trackingNumber": "1Z{{$string.alphanumeric(length=16)}}",
"shippedAt": "{{$date.recent(days=3,format='yyyy-MM-dd')}}"
}
期待値`order-cancelled`、条件:パスパラメータ`id`が`5002`と等しい。
{
"id": 5002,
"status": "cancelled",
"total": 0,
"cancelledAt": "{{$date.recent(days=1,format='yyyy-MM-dd')}}",
"refundIssued": true
}
最後に、条件なしで一般的な保留中注文を返す期待値を追加します。これにより、他のどのIDでもフォールスルーせずに有効なレスポンスが返されます。特定のルールをキャッチオールのルールの上に配置して保存すると、あらゆる注文ステータスをオンデマンドでレンダリングするモックが完成します。条件を組み合わせることも可能です。パス条件に加えてヘッダー条件を追加すると、両方が満たされる必要があります。Apidogは複数の条件をANDロジックで結合するためです(ドキュメントの用語では条件の交差)。
条件はボディとパスに限定されません。クエリパラメータ、ヘッダーパラメータ、クッキーパラメータ、さらにはIPアドレスに基づいて一致させることもでき、テスト中に特定のクライアントへのレスポンスを制限することができます。
オンデマンドでのエラー状態の強制
壊れたレスポンスをテストするために、壊れたバックエンドは必要ありません。期待値と**More**タブを使えば、どのようなステータスでも自由自在に設定できます。
`500`エラーを強制するには、クライアントから制御できる条件(たとえば、`X-Mock-Scenario`ヘッダーが`server-error`と等しいなど)を持つ期待値を追加します。その**Response data**を現実的なエラーボディに設定し、**More**タブで**HTTPステータスコード**を`500`に設定します。
{
"error": "internal_error",
"requestId": "{{$string.uuid}}",
"message": "Something went wrong on our end. Please retry."
}
これで、同じエンドポイントがデフォルトでは通常の`200`を返し、そのヘッダーを送信するたびに`500`を返します。`404`、`429`(**More**タブで`Retry-After`ヘッダーを設定)、または`503`についても同様に行います。これにより、フロントエンドのエラーハンドリングがついに何かをキャッチできるようになります。これらのレスポンスを自動チェックでアサートする場合、APIアサーションのガイドがこの設定と相性が良いでしょう。
共有プロジェクトに関する1つの詳細:各期待値は、期待値リストからローカルおよびクラウドのモック環境に対して個別にオン/オフを切り替えることができます。これにより、ローカルでは`500`ルールを有効にしておき、チームメイトが利用するクラウドモックでは無効にしておくことができます。
ルールが十分でない場合:モックスクリプト
期待値は宣言的です。一致して値を返しますが、計算はできません。リクエストから派生したフィールド、明細項目から合計された金額、あるいは複数の入力に基づいて形状が変わるボディが必要な場合は、モックスクリプトを使用します。
モックスクリプトは、モックレスポンスに対して実行されるJavaScriptです。**Mock**タブの下部にある**Mock Script**セクションにあり、トグルスイッチで有効にします。このスクリプトは2つのグローバルオブジェクトを公開します。
- `$$.mockRequest`:`getParam(key)`を介して着信リクエストを読み取り、`headers`、`cookies`、`body`、`formdata`、`urlencoded`も利用できます。
- `$$.mockResponse`:`setBody()`、`setCode()`、`setDelay()`、`json()`、そして`headers`および`code`プロパティを介して、送信レスポンスを形成します。
const body = $$.mockRequest.body;
const items = body.items || [];
const subtotal = items.reduce((sum, item) => {
return sum + item.price * item.quantity;
}, 0);
const currency = $$.mockRequest.headers["x-currency"] || "USD";
$$.mockResponse.setCode(201);
$$.mockResponse.setBody({
orderId: Math.floor(Math.random() * 90000) + 10000,
currency: currency,
subtotal: subtotal,
tax: Number((subtotal * 0.08).toFixed(2)),
total: Number((subtotal * 1.08).toFixed(2))
});
流れはこうです:Smart mockが初期レスポンスを生成し、スクリプトが`$$.mockRequest`と現在の`$$.mockResponse`を読み取り、ロジックを適用し、`$$.mockResponse.setBody()`(および必要に応じて`setCode`、`setDelay`、`headers`)を呼び出し、エンジンが最終結果を返します。配列メソッドや日付計算でロジックをさらに深めたい場合は、MDN JavaScriptリファレンスが強力な味方となるでしょう。
人々を悩ませる一つのルール
モックスクリプトはSmart mockでのみ機能します。モック期待値やレスポンス例には適用されません。これは最も重要な点であり、心に留めておく必要があります。モックスクリプトを期待値ベースのレスポンスと組み合わせることはできません。期待値がリクエストに一致した場合、スクリプトは実行されません。したがって、エンドポイントごとにどちらか一方を選択してください。固定条件に基づいて分岐し、事前定義されたボディを返す場合は期待値を使用します。Smart mockが生成したベースから計算された出力が必要な場合は、モックスクリプトを使用します。
優先順位がどのように解決されるか
これらをまとめると、Apidogがすべてのモックリクエストに対して実行する順序は次のとおりです。
- 期待値を上から下へとチェックします。すべての条件が一致する最初の期待値が優先され、そのレスポンスが返されます。これがカスタムルールがSmart mockに勝る理由です。一致する期待値は、その下のすべてをショートサーキットします。
- どの期待値も一致しない場合、Apidogは**プロジェクト設定 - 機能設定 - モック設定**で設定した**モックメソッドの優先順位**にフォールバックします。これはSmart mock(およびそれにアタッチされたモックスクリプト)がレスポンスを生成する階層です。
メンタルモデルはシンプルです。まず具体的なルール、次に生成されたデータです。期待値を最も具体的なものから最も一般的なものの順に並べ、確実に一致させたい場合は、一番下に条件なしのキャッチオールを置き、残りはSmart mockに任せます。各レイヤーをいつ利用すべきかについてさらに詳しく知りたい場合は、APIモックのユースケースガイドが一般的なシナリオを機能にマッピングしています。
リリース前に知っておくべき注意点
いくつかの制約を知っておくことで、混乱するデバッグセッションを避けることができます。
- パラメータ条件は`{{variables}}`をサポートしていません。Apidogのプロジェクト変数や環境変数はモック期待値内で使用できないため、条件にはリテラル値を記述してください。
- ボディパラメータの条件はJSONのみで、XMLではありません。また、名前フィールドのJSONパスを介して一致させる必要があります。
- 条件におけるリクエストボディのフォーマットは、API仕様と一致する必要があります。フォームデータのエンドポイントは、JSONではなくフォームデータの配置でモックする必要があります。
- モックスクリプト内にはログ関数がなく、`pm`オブジェクトは利用できません(テストスクリプトとは異なる実行環境です)。また、Apidog変数も使用できません。スクリプトのロジックは自己完結型に保ってください。
これらの機能はいずれもドキュメントでプランの制限が示されていません。ローカルとクラウドの唯一の違いは機能的なものです。前述した環境ごとの独立したオン/オフ切り替えであり、有料の壁ではありません。
Apidog CLIでワークフローを自動化する
ApidogでのモックはGUIとクラウド機能です。モックエンジンはローカルおよびクラウドのモックURLからエンドポイントを提供し、実行中のモックサーバーを起動するCLIコマンドはありません。Apidog CLIが追加する機能は、これらのモックが構築されるリソースを制御することです。
モックレスポンスはエンドポイントスキーマから生成されるため、モックの正確性は仕様の正確性に追随します。CLI、およびそれを駆動するAIコーディングエージェント(Cursor、Claude Code、Trae、Codex)は、プロジェクト内のエンドポイントとスキーマを作成および更新できます。コードで契約を変更し、同期するだけで、誰もアプリを再開することなくモック出力は正確に保たれます。
モックがフロントエンドの作業をアンブロックしたら、同じプロジェクトのテストシナリオがCIでヘッドレスに実行され、モックが記述した契約に対して実際のバックエンドを検証します。
apidog run -t <scenario_id> -e <env_id> -r cli
この単一のコマンドがテストシナリオを実行し、結果を報告するため、モックと検証は一つの真理の源を共有します。Apidog CLIインストールガイドがセットアップをカバーし、GitHub ActionsでのApidog CLIウォークスルーがこれをパイプラインに組み込みます。
よくある質問
条件が正しく見えるのに、期待値が無視されるのはなぜですか? ほとんどの場合、順序またはフォーマットの不一致です。期待値は上から下へと評価され、最初に一致したものが優先されるため、特定のルールの上に広範な条件なしのルールがあると、そのリクエストを「飲み込んで」しまいます。また、ボディのフォーマットが仕様と一致しているか(JSONボディの場合はJSONパス、フォームエンドポイントの場合はフォームデータの配置)を確認してください。再確認したい場合は、APIモックの概要でセットアップの基本が説明されています。
モックスクリプトとモック期待値を同じレスポンスで利用できますか? いいえ。モックスクリプトはSmart mockでのみ実行されます。モック期待値やレスポンス例では無視されます。期待値が一致した場合、スクリプトは実行されないため、エンドポイントごとにいずれかのアプローチを選択してください。ルールベースの分岐には期待値を、計算された出力にはスクリプトを使用します。
デフォルトの200を壊さずに401や500を返すにはどうすればよいですか? クライアントから制御できる条件(ヘッダーがうまく機能します)を持つ専用の期待値を追加し、その「More」タブを開いてHTTPステータスコードを設定します。デフォルトのレスポンスは`200`のままで、エラーは条件が一致した場合にのみ発生します。
条件で環境変数を使用できますか? いいえ。Apidogの`{{variable}}`値はモック期待値内では使用できず、パラメータ条件も`{{variables}}`をサポートしていません。条件にはリテラル値を使用してください。
どの期待値も一致しなかった場合はどうなりますか? Apidogは、プロジェクト設定 - 機能設定 - モック設定のモックメソッドの優先順位にフォールバックし、Smart mockがスキーマからレスポンスを生成します。代わりに特定のフォールバックを保証する方法は、条件なしのキャッチオール期待値を追加することです。
まとめ
Smart mockは一般的なケースを処理し、モック期待値は「もし〜ならば」という条件を含むすべてを処理します。たとえば、既知のユーザーには`200`を、それ以外には`401`を、ステータスごとに異なる注文ボディを、オンデマンドで`500`を返します。ルールでは表現できない計算された出力が必要な場合にのみモックスクリプトを使用し、それがSmart mock単独で実行されることを覚えておいてください。優先順位(まず具体的な期待値、次に生成されたデータ)を念頭に置けば、実際のAPIと同じようにモックが分岐するでしょう。Apidogをダウンロードして、最初の条件付きモックを無料で構築しましょう。クレジットカードは不要です。
