スーパークラスのメソッド呼び出しをモックできますか?
質問
場合によっては、クラスメソッドをテストし、スーパークラスメソッドの呼び出しを期待したいことがあります。 easymockまたはjmockを使用してJavaでこの期待を実現する方法を見つけませんでした(それは不可能だと思います)。
スーパークラスメソッドロジックを使用してデリゲートを作成し、それに期待を設定する(比較的)きれいなソリューションがありますが、そのソリューションを使用する理由と例はありませんか?
ありがとう
解決
まあ、必要ならできます。 JMockit に慣れているかどうかはわかりません。ぜひチェックしてください。現在のバージョンは0.999.17です。それまでの間、見てみましょう...
次のクラス階層を想定します:
public class Bar {
public void bar() {
System.out.println("Bar#bar()");
}
}
public class Foo extends Bar {
public void bar() {
super.bar();
System.out.println("Foo#bar()");
}
}
次に、 FooTest.java
でJMockitを使用すると、 Foo
から Bar
を実際に呼び出していることを検証できます。
@MockClass(realClass = Bar.class)
public static class MockBar {
private boolean barCalled = false;
@Mock
public void bar() {
this.barCalled = true;
System.out.println("mocked bar");
}
}
@Test
public void barShouldCallSuperBar() {
MockBar mockBar = new MockBar();
Mockit.setUpMock(Bar.class, mockBar);
Foo foo = new Foo();
foo.bar();
Assert.assertTrue(mockBar.barCalled);
Mockit.tearDownMocks();
}
他のヒント
JMockit 1.22を使用して@Cem Catikkasの回答を拡張します:
@Test
public void barShouldCallSuperBar() {
new MockUp<Bar>() {
@Mock
public void bar() {
barCalled = true;
System.out.println("mocked bar");
}
};
Foo foo = new Foo();
foo.bar();
Assert.assertTrue(mockBar.barCalled);
}
@MockClassアノテーションが付けられた静的クラスは不要で、MockUpクラスに置き換えられます。
スーパーコールをモックアウトするとは思わない-依存関係の動作ではなく、クラス自体の動作の一部である動作のように感じます。モックは、依存関係を何よりも行うべきであると常に感じます。
モックアウトしたい種類のコールの良い例はありますか?このような呼び出しをモックアウトする場合、継承ではなく構成を検討する価値がありますか?
Animated Transitionsサンプルテストスイートには、JMockit Expectations APIを使用して、まさにそれを実行する(つまり、スーパークラスメソッドで予期される呼び出しを指定する)テストがいくつかあります。たとえば、 FadeInTest テストケース。
いいえ、 jMock でスーパークラスメソッドをモックする方法はありません。
ただし、問題に対する迅速で不潔な解決策があります。クラスAとクラスBがAを拡張しているとします。BでメソッドAa()をモックしたい場合、テストコードでクラスCを拡張し、メソッドCa()をオーバーライドできます(単にsuperを呼び出すか、null、idを返す関係ない)。 Cをモックした後、Bを使用するすべての場所でモックを使用します。
スーパーコールの傍受は非常にきめ細かすぎます。分離をやりすぎないでください。