カイゼンにっき。

@hyokota です。主にtwitterに呟いていますが、twitterに書ききれない事をここに綴って行こうかと。

モックの本当の価値とは? 〜『JUnit実践入門』写経・実践会 in 横浜#3 #junitbook に参加しました〜

『JUnit実践入門』写経・実践会 in 横浜 #3 - connpassに参加させて頂きました。

下記、勉強会にインスパイアされて、私が学んだ/感じたことのまとめです。
※例によって、勉強会のまとめではなく、内容のごく一部にしか触れていないことにご注意を。
※そして、開催者によるこれ以上ないクオリティのまとめ記事はこちら

次回の募集も始まっているので、ご興味をもたれた方は是非!

モックとスタブの違い

「モック」のためのライブラリを用いて、「スタブ」的なことも問題なく実現できる(特にMockitoのようなlenient mock)ので混同しやすいが、役割も注目点も違う。

モックの価値とトレードオフ



モックの本当の価値

モックを用いる事で、SUTと依存オブジェクト(これをモックにする)の、今注目すべきやりとりに集中し、テストとして定義することが出来る。これはどのような価値を生み出すのか。正直なところ、私にはまだ熱く語れるほどの実感がない*1

ただ、実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)にはこうある。

私たちは、実行時のシステムをコミュニケーションしあうオブジェクトの網の目と捉える。したがって設計時には、必要な機能を実現するために複数のオブジェクトがどう協力し合うかという点に注力する。確かに、クラス構造はうまく設計したい。しかし、オブジェクト間のコミュニケーションパターンの方が重要だと考えるのである。
Javaのような言語では、インターフェースを使ってオブジェクト間のやり取りに使えるメッセージを定義できる。しかし同時に、コミュニケーションのパターンも定義する必要がある。これは言わば、コミュニケーションプロトコルだ。命名と規約を使って出来ることはやるが、インターフェース同士の関係やインターフェース内のメソッドの関係を記述する手だてが、プログラミング言語には用意されていない。そのため、設計において非常に重要な箇所が暗黙的なままになってしまうのだ。
私たちがモックオブジェクトと共にTDDを用いるのは、こうしたコミュニケーションプロトコルを明示するためだ。

私たちが主張して来たのは、互いに命令を送り合うオブジェクトに集中すること、そして、その状態を問い合わせる方法を一切露呈させないということだ。しかしこれでは、ユニットテストでアサートする手段がなくなってしまったのではないだろうか。

テスト対象のオブジェクトの隣接オブジェクトを、テスト中に代用品と置き換えるやり方の一つとして、…モックオブジェクトを使うことで、起点となるイベントに対して、テスト対象のオブジェクトがどのように隣接モックとコミュニケーションするかについて、自らが期待する内容を定義できるのだ。こうした定義のことをエクスペクテーションと呼ぶ。テストをしている間は、期待された通り呼び出されたことをモックオブジェクトがアサートする。

こうしたテスト基盤を適切に用いれば、TDDでの作戦を変える事が出来る。
私たちはただテスト対象のオブジェクトだけをテストしたいのだということ、それから、隣接オブジェクトがどのようなものであるかが、既に分かっているということだ。しかし実際には、ユニットテストを書いている時点では、こうした協調して動作するオブジェクトは存在していなくても構わない。テストを使う事で、自分たちのオブジェクトが必要とする補助的なロールを明らかにすることができるのだ。こうしたロールはJavaのインターフェースとして定義され、実際に実装されるのはシステムの残りの部分を開発するときだ。私たちはこれを、インターフェースの発見と呼んでいる。

コードを書く上で非常に重要な観点に触れた気がする。


実践と、合わせてGOOSの熟読をしたい。

参考書

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)xUnit Test Patterns: Refactoring Test Code (Addison-Wesley Signature Series (Fowler))SQLアンチパターンレガシーコード改善ガイド (Object Oriented SELECTION)プログラミングGROOVY

*1:恥ずかしながら、私は普段スタブは使っても「モック」を使った事がない。