子コンストラクターの単体テストで、親クラスの機能をモックまたはスタブする方法を探しています。親クラス自体は設計が不十分ですが、契約上の合意により変更できません。既に PowerMockito を使用していますが、PowerMock(EasyMock) も承認済みライブラリのリストに含まれています。単体テストを機能させるためのこれまでの最善の試みとともに、簡略化されたコードを次に示します。
/**
* The class Parent is locked
*/
public class Parent {
private final Integer x;
private final Integer y;
public Parent(Integer x) {
this.x = x;
this.y = loadY();
}
private int loadY() {
// Actual code loads a bunch of stuff from DB
throw new RuntimeException();
}
protected Integer getSum() {
return x+y;
}
}
/**
* This code is not locked, but Child MUST extend Parent and foo MUST be final.
*/
public class Child extends Parent{
private final Integer foo;
public Child(int x) {
super(x);
foo = getSum();
}
public Integer getFoo() {
return foo;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({Child.class, Parent.class})
public class ChildTest {
@Mock
private Parent par;
@Test
public void testGetFoo() throws Exception {
MemberModifier.suppress(MemberMatcher.constructor(Parent.class, Integer.class));
PowerMockito.whenNew(MemberMatcher.constructor(Parent.class)).withNoArguments().thenReturn(par);
Mockito.when(par.loadY()).thenReturn(new Integer(3));
Mockito.when(par.getSum()).thenReturn(7);
Child child = new Child(4);
Assert.assertEquals(new Integer(7), child.getFoo());
}
}
クラス Child が Parent を拡張し続け、foo が final である限り、クラス Child を編集することはできますし、喜んで行いますが、Parent を編集することは決してできません。getSum() への呼び出しをモックする方が理想的です。これにより、その呼び出しの検証が可能になります (ここでは関係ありませんが、他のシナリオでは可能性があります)。それでも、loadY() のモックや child.y の状態の設定は許容できるようですが、child.foo の設定は正しくないようです。私はこれを理解しようとして Web サイトと Eclipse の間を行ったり来たりして 1 日の大部分を費やしてきましたが、これまでのところ、すべての実行で予想される RTE または NPE が得られています。何か案は?