こんなクラスがあるとする。
public class Foo {
private final Bar bar = new Bar();
public String hoge() {
return this.bar.baz().hoge();
}
} 見ての通り、Foo は メソッド hoge()の中で、関連オブジェクト bar から取得した baz に、hoge() 処理を移譲している(日本語にすると、なんのこっちゃだが…)。
Bar と Baz は以下のような感じで後回しにしてある。
public class Bar {
public Baz baz() { throw new AssertionError(); }
}
public class Baz {
public String hoge() { throw new AssertionError(); }
}
ここで、Foo#hoge() をテストするにはどうするか。つまり以下の/* ??? */ のところに何を入れたらテストできるか。
public class FooTest {
@Test public void hoge() {
/* ??? */
Assert.assertEquals("hello", new Foo().hoge());
}
}
とりあえず2個だけ例を書いてみると(ちょっとずつニュアンスの違うものを何通りも書けるが)、以下のようになる。
@Test public void hoge1() {
new Expectations() {
@Mocked("baz") Bar bar;
@Mocked("hoge") Baz baz; {
bar.baz(); result = baz;
baz.hoge(); result = "hello";
}
};
Assert.assertEquals("hello", new Foo().hoge());
}
@Test public void hoge2() {
new NonStrictExpectations() {
Bar bar;
Baz baz; {
bar.baz(); result = baz; times=1;
baz.hoge(); result = "hello"; times=1;
}
};
Assert.assertEquals("hello", new Foo().hoge());
}JMockit を使い始めたばかりだと、結構、とまどうんじゃないかと思う。デバッガで追ってみると、例えば "result = baz" のところで、初期化していないはずの baz に何故かインスタンスが設定されているし、代入されたと思った result が null のままだったりして、普通の Java ソースの感覚で読んでいると訳が分からなかったりする。
とは言ってもまあ、すぐ慣れるし、そうなると逆に、JMockit 無しのテストを考える事が、時折難しく感じられてくる。
ただ、JMockit を使うと後付けテストもかなり簡単になるにはなるけど、やっぱりテストファーストが基本というのは押さえておいた方が良い。この例はもともと簡単だから、それほど大変なテストコードにはならないけど、もっと複雑なものになると、後付けとテストファーストではテストコーディングの生産性が大きく違ってくる。
====
テストファースト版は、こっちに書いた。
0 件のコメント:
コメントを投稿