Mockito间谍失败,因为无法初始化类成员



我有以下代码:

public class MyClass() {
private MyObject myObject = getMyObject();
public MyObject getMyObject() {
if (myObject == null) {
myObject = MyStaticClass.createMyObject();
}
return myObject;
}
// heaps more methods
}
public class MyTest() {
private MyClass spyMyClass = spy(new MyClass());
public MyTest() {
doReturn(null).when(spyMyClass).getMyObject();
}
@Test
public void someTest() {
ClassUnderTest c = new ClassUnderTest();
assertTrue(c.someMethod(spyMyClass));
}
}

测试失败,错误Could not initialise class MyStaticClass。原因是这个静态类正在初始化更多在测试期间不可用的其他类对象(例如数据库),我不在乎,因为您可以看到在调用方法getMyObject()时返回 null。

但是这个意图也失败了,因为在到达doReturn(null)行之前,测试已经在spy(new MyClass())行失败,在该行中,它调用getMyObject()来初始化私有成员myObject

上述情况的解决方法是使用mock(MyClass.class)而不是spy(new MyClass()),这样私有成员myObject就不会被初始化,因此不会调用真正的getMyObject()方法。

但是这种解决方法给我带来了另一个麻烦,因为这意味着我将不得不为MyClass中的堆更多方法进行一些配置(甚至只是为了doCallRealMethod())。

问题:有没有另一种解决方案,我仍然可以在MyClass实例上使用间谍,这样我就可以忘记在此类中配置这些堆更多的方法,但我可以绕过Could not initialise class MyStaticClass错误?

附言我不能简单地使用 Power Mock 来模拟MyStaticClass因为我已经在使用另一个测试运行器进行MyTest。除非你的答案可以显示同时运行两个测试运行程序是多么容易,而无需实现将两者组合在一起的新混合测试运行程序。


感谢亚当,现在我有一个很好的工作代码:

public class MyTest() {
private MyClass spyMyClass = spy(new MyClass() {
@Override
public MyObject getMyObject() {
return null;
}
});
@Test
public void someTest() {
ClassUnderTest c = new ClassUnderTest();
assertTrue(c.someMethod(spyMyClass));
}
}

创建一个MyClass的子类并在private MyClass spyMyClass = spy(new TestMyClass());中使用它:

class TestMyClass extends MyClass {
@Override // fortunately, the original method called in constructor can be overridden (what could be considered bad)
public MyObject getMyObject() {
// something that does not fail the constructor
}
}

通常,这是问题的潜在原因,因为您在构造函数中调用非私有、非最终方法。对于测试用例,这可能是可以接受的。

稍微离开一点,我想看看这个MyClass对象的责任是明智的。是不是做得太多了,因此很难测试和互动?这通常会导致"难以嘲笑"的综合症。

相关内容

  • 没有找到相关文章

最新更新