手元にはあったが長らく積んでいたJUnit実践入門の11章:テストダブルの章を読んでまとめを書きました.実際のところMockitoってなんだかいままでよく分からない存在だったけど,手をつけてみるとかなりお手軽&便利なものでした.学習コストもそれほど高くないので,何となく敬遠していたり,テストってどう書けば良いのかよくわかっていない私のような人がいたら是非,Mockitoを使ったテストコードを実際に書いてみることをお勧めします.

テスト対象クラスが依存するクラス・モジュール問題

理想的なユニットテストは,依存するすべてのクラスや外部システムを使用したもの  
* なぜなら,実際に動くコードはそういう状況で動くのだから
* しかし依存する本物のオブジェクトを常に使用できるとは限らないし,ユニットテストで扱いにくいオブジェクトもある
* このようなときにテストしやすいようにリファクタリングしたり,本物のオブジェクトの代役となるオブジェクトに置き換えてテストを行うという手法が用いられる

テスタビリティを高めるリファクタリング

  • JavaのDateの精度はミリ秒であるため次のコードは,テストに成功したり失敗したりする
  • 乱数を使ったコードは当然ながらテストが書きにくい
  • このようにインスタンス生成のタイミングや環境に依存してしまう部分が含まれるコードのテストは難しい

インスタンス生成の部分を抽出してファクトリメソッドを作ると,ここをOverrideして振る舞いを変えることができ,依存度を下げることができる

今回の例に対してはやや過剰な実装とはなるが,振る舞いの複雑なメソッドをオブジェクトに切り出し,委譲を使って差し替え可能にするという方法もある

テストダブル:スタブ/モック/スパイ

  • テスト対象となるクラスが他クラスに依存していないケースはほとんどない
  • 依存しているクラスもまた他のクラスに依存している
  • この状態でテストを行うメリットは実行時に近い状態でテストができること
  • デメリットはテスト対象以外の問題を原因としてテストが失敗する可能性があること
  • このとき依存しているオブジェクトの代役(スタブ・モック)を使うことをテストダブルという

スタブ

  • スタブとは依存するクラスやモジュールとして代用できる仮のクラス・モジュール
  • 以下のようなときに用いられる
    • 依存オブジェクトが予想できない振る舞いを持つとき
    • 依存オブジェクトのクラスがまだ存在しないとき
    • 依存オブジェクトの実行コストが高く,簡単に利用できない
    • 依存オブジェクトが実行環境に強く依存している
  • 例えば乱数を用いるようなクラスのテストは,依存オブジェクトRandomが予想できない振る舞いを持つためスタブを使うと良い
  • コード的には次のようなものになる

モック

  • スタブと同様にテスト対象が依存するクラスやモジュールの代用として使用されるもの
  • スタブはメソッドの返り値を予想可能な値にすることにより、依存クラス・モジュールが正しく利用できているか確かめるもの
  • モックはメソッドが正しく呼び出されているかを検証するもの

スパイ

  • 基本的にテストはメソッドへの入力に対して出力を検証する
  • 従ってvoid型のメソッドの検証はやりにくい
  • そこでロガーに書き込まれた内容を検証に使うスパイという手法がある
  • 基本的にはロガーのロギング機構にStringBufferへのappendの処理を追加して,検証時にtoStringして文字列比較するという単純なもの

Mockitoでスタブ・モックを作る

  • mockitoが適当に使える状況にしておく
  • Mock.mock(モックを作りたい対象のクラス)でモックが作れる
  • `where(モックのインスタンス.メソッド()).thenReturn(期待する返り値)Pで振る舞いを持たせられる
  • その他,コードを見ればきっと分かる!
  • 基本的にmockitoの使い方自体は簡単だけれど,そもそもスタブ・モックとは何かを理解できていないところがmockitoを使う上での最大の壁になると感じた
  • 現に本を読んで自分はちゃんとスタブ・モックがなにかを理解できていなかったので反省した

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です