jMockは、JUnitによるユニットテストで使うツールです。
モックオブジェクトとは一体何でしょうか。
簡単に言うと、あるインスタンスの動作を代行するものです。
public class Sample {
private External external;
public void some() {
...
external.someExternal(...);
...
}
public void setExternal(External external) {
this.external = external;
}
}
こんなコードがあったとします。
ここでSampleクラスのユニットテスト(以下UT)を書くとしましょう。
モックを使わない方法だと、例えば以下のようになります。
public void SampleTest {
@Test
public void testSome() {
Sample sample = new Sample();
External external = new External(...);
external.init();
sample.setExternal();
sample.some();
...
}
}
このように、実際にsomeメソッドを呼び出すときと同じように
Externalインスタンスを生成してそれを渡しています。
これはこれで一つの手段なのですが、いくつかの問題点があります。
例えばExternalクラスが変更された時など、このUTまで変更する必要が出てきます。
本来このUTはSampleクラスのUTなのでExternalの変更に依存したくないのです。
UTとは本来、単一クラスのみに関するテストをするべきです。
しかしこの方法だと、結果的にExternalクラスのテストも
少なからず行なっていることになります。
他にもExternalクラスを使うクラスが複数ある場合、
これら全てのUTで同様の処理を入れなければなりません。
テストコードにも重複する処理はなるべく入れたくないはずです。
このような欠点を解決するための一つの手法が、モックオブジェクトです。
上の例で言うと、Externalインスタンスを通常通り作成するのではなく
「ダミーの」Externalインスタンスを作成します。
こうすることによって、Externalクラスの変更があっても
SampleのUTは変更する必要が無くなります。
また、本来のExternalクラスは一切使わないので
テスト範囲が広がることもありません。
ここで一つ重要な点があります。
モックで使用するインスタンスは必ずインターフェイス化されていなければなりません。
先程の例で言うと、Externalクラスではなく
Externalインターフェイスを用意する必要があるという事になります。
もしExternalがクラスだと、そのモックオブジェクトを作るためには
以下のような感じになってしまいます。
public MockExternal extends External {
@Override
public void sumeExternal() {
...
}
}
このように、全てのpublicメソッドをオーバーライドして
実装する必要が出てきてしまいます。
こういうモックオブジェクトは過去には実際使われてきた手法なのですが
非常に手間が掛かりコードが汚くなる為に、あまり好ましくない手法なのです。
Externalをインターフェイスにすると、以下のような感じになります。
public interface External {
void sumeExternal();
}
public class ExternalImpl implements External {
public void sumeExternal() {
...
}
}
モックオブジェクトおよびテストコードは以下のような記述になります。
public class MockExternal implements External {
public void sumeExternal() {
...
}
}
public void SampleTest {
@Test
public void testSome() {
Sample sample = new Sample();
External external = new MockExternal();
sample.setExternal();
sample.some();
...
}
}
これで、MockExternal は External には依存していますが
メインの実装である ExternalImpl からは完全に独立しています。
モックを実装から独立させる。
これがインターフェイスを使う最大の理由です。
さて、前置きが長くなりましたが。
jMockとは、このモックオブジェクトを
より簡単に使うための便利ツールです。
以下では、実際にjMockを使ってテストコードの書き方を紹介していきます。