
Summary
この文書の要点
- API契約テストはレスポンス形とステータスコードを確認する。
- 正常系より先に入力不正と権限不足を用意する。
- リクエスト、レスポンス、エラー形式をZod schemaで固定し、Vitestで回帰を見る。
- 正常系だけでなく、認証不足、入力不正、権限不足の契約をテストする。
どこが設計の難所か
TypeScriptで型が通っていても、HTTP APIとしての契約が変わることがあります。ステータスコード、エラー本文、日付形式、nullの扱いが変わると、フロントエンドや外部連携が壊れます。
すべてのAPIに重い結合テストを書くと実行時間が伸びます。一方で、重要な更新系や認証が絡むAPIは、単体テストだけでは不十分です。リスクに応じたテスト粒度が必要です。
TypeScriptでフロントエンドとAPIを書いていても、実行時のレスポンスが型通りとは限りません。APIのフィールド名変更やエラー形式の変更は、コンパイルを通っても画面を壊すことがあります。
境界をどう切るか
Vitestでは、Honoアプリをメモリ上で呼び出し、HTTPレスポンスとして検証します。正常系、入力不正、権限不足、存在しない対象、状態競合のケースを用意します。
設計では、API契約を型定義だけでなく、実行時schemaとテストで固定します。VitestでHono handlerやAPI clientを呼び、レスポンスがschemaを満たすか、ステータスコードとエラーコードが期待通りかを確認します。
実装で効く細部
テストデータはファクトリで作り、DBを使う場合はテストごとに分離します。Zodスキーマの単体テストではなく、実際のルートへリクエストを投げて、レスポンス形式まで確認します。エラーコードは文字列定数として扱います。
Zod schemaをAPIレスポンスの境界に置き、テストでは成功レスポンスと失敗レスポンスの両方をparseします。DBや外部APIはテスト用adapterへ差し替え、契約の確認に集中できるようにします。
- 画面が依存するレスポンスだけでなく、エラーbodyの形もschema化する。
- optional追加と必須変更を区別し、互換性を壊す変更をレビューで見つける。
- 契約テストには代表的な権限状態を含める。
壊れ方を観測する
CIでは、API契約テストを高速に回し、重いE2Eとは分けます。レスポンス全体のスナップショットは変更に弱いため、重要なフィールドを明示的に検証する方がレビューしやすいです。
検証では、API実装テスト、API clientテスト、画面側のmockデータが同じschemaを参照しているかを確認します。契約テストが落ちた時は、実装バグか契約変更かをPRで明確にします。
捨てた選択肢とトレードオフ
契約テストを増やすと変更時にテスト修正が必要になります。しかし、それはAPI契約が変わることを明示する機会でもあります。内部実装のテストより、外部に見える振る舞いを優先するのが効果的です。
契約テストを細かく書くと変更時の修正は増えますが、意図しない破壊的変更を防げます。すべてのフィールドを固定するのではなく、画面や外部連携が依存する部分から優先するのが現実的です。
現場に残す判断軸
Vitestは関数テストだけでなく、API契約の回帰検知にも使えます。HTTP境界で入力と出力を確認することで、AIエージェントや複数開発者による変更にも強くなります。
Vitestの契約テストは、バックエンドの単体テストではありません。APIを使う側との約束を実行時に確認することで、型だけでは拾えないずれを減らせます。


