はじめに
個人的な経験に紐づく見解なので、良いところは真似て、悪いところはスルーしてください。理想とスケジュールを加味した現実解のような雰囲気で書いています。
前提条件
サーバサイドの構成はこんな感じです(想定は Java)
- Controller: リクエストを受け取る所。簡単な validation (必須チェックとか文字種チェックとか)を行い、ApplicationService を呼び出す
- ApplicationService: トランザクション管理や Domain,Repository を呼び出す。ロジックは持たせたくない。DI想定
- 正常終了できなければ例外として throw するくらいのノリ
- Domain: モデルとそれに対する振る舞いをまとめたもの
- 内部で永続化とか外部サービス呼び出しとかは意識しない
- DomainService: 複数の Domain を組み合わせて結果を導出するレイヤー。DI想定
- Repository: 永続化した Domain に関する Interface 定義。DI想定
- Infrastructure: Repository の実装
イメージ
Controller が意識するレイヤー
ApplicationService が意識するレイヤー
Domain が意識するレイヤー
自分の中に閉じます
DomainService が意識するレイヤー
自分の中に閉じます。Domain は意識しますが、パラメータで貰います
Infrastructure が意識するレイヤー
自分の中に閉じます
各レイヤーでの Unit Test の観点
Controller
ApplicationService の呼び出しを Mock 化して Unit Test を書きます。観点は以下の通りです。
- レスポンスの verify
- Mock 化したメソッドの呼び出し回数、引数の verify
- Controller で引数を加工しているなら、それを加味して verify すべきです
ApplicationService
Repository / DomainService の呼び出しを Mock 化して Unit Test を書きます。Repository が返す Domain は 実インスタンスで良いと思います。観点は以下の通りです。
- 戻り値の verify
- Mock 化したメソッドの呼び出し回数、引数の verify
- ApplicationService で引数を加工しているなら、それを加味して verify すべきです
Domain
前提条件となる状態を作ってテストします。Mock は不要だと思います。
- 戻り値の verify
- 内部の状態を変更する場合の verify
DomainService
テストの前提条件となる Domain を作ってテストします。Mock は不要だと思います。
- 戻り値の verify
Infrastructure
自分の実装のみ意識します。永続化が RDBMS なら実際にアクセスします。
Integration Test
Controller からの呼び出しを一気通貫でテストします。実際問題、全てのパターンはしなくても良いと思いますが、
- レスポンスの verify
- 永続化するエンドポイントの場合、想定通りに永続化されているか
の verify はすべきだと思います
まとめ
チーム内でレイヤー毎にテストを書く方針を決めておくとスムーズに開発できると思います。
Mock 使えば簡単にテストを通すことはできますが、「Mock が想定通りに呼ばれたか」の verify が漏れてるとテストの意味が半減なので、ここは面倒でもやった方が良いと思います(これが書きたかっただけ)。
それでは良いテストライフを!