我正在寻找一种方法来模拟或以其他方式在其子构造函数的单元测试中存根父类的功能。Parent 类本身设计得很糟糕,但由于合同协议而无法触及。我们已经在使用 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 是最终的,但我无法以任何方式编辑 Parent 。模拟对 getSum() 的调用会更理想,因为这将允许验证该调用(此处不相关,但可能在其他情况下)。尽管如此,模拟 loadY() 或设置 child.y 的状态似乎是可以接受的,但设置 child.foo 似乎并不正确。我花了一天的大部分时间在网站和 eclipse 之间来回弹跳,试图弄清楚这一点,但到目前为止,每次运行都会导致预期的 RTE 或 NPE。有任何想法吗?