Java Mockito spy失败,因为无法初始化类成员
我有以下代码:Java Mockito spy失败,因为无法初始化类成员,java,mocking,mockito,powermock,powermockito,Java,Mocking,Mockito,Powermock,Powermockito,我有以下代码: public class MyClass() { private MyObject myObject = getMyObject(); public MyObject getMyObject() { if (myObject == null) { myObject = MyStaticClass.createMyObject(); } return myObject; } //
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));
}
}
测试失败,出现错误无法初始化类MyStaticClass
。这个静态类的原因是初始化了许多其他在测试期间不可用的类对象(例如数据库),我不在乎,因为您可以看到,当调用方法getMyObject()
时,我可以返回null
但是这个意图也失败了,因为在到达doReturn(null)
行之前,测试已经在spy(new MyClass())
行失败,在该行中,它调用getMyObject()
初始化私有成员myObject
上述情况的一种解决方法是使用mock(MyClass.class)
而不是spy(new MyClass())
,这样私有成员myObject
不会被初始化,因此不会调用realgetMyObject()
方法
但是这种解决方法给我带来了另一个头疼的问题,因为这意味着我将不得不对MyClass
中的大量方法进行一些配置(甚至仅仅是doCallRealMethod()
)
问题:是否还有另一种解决方案,我仍然可以在MyClass
的实例上使用spy,这样我就可以忘记在这个类中配置那些堆更多的方法,但我可以绕过无法初始化类MyStaticClass
错误
另外,我不能简单地使用powermock来模拟MyStaticClass
,因为我已经在为MyTest
使用另一个测试运行程序。除非你的答案能说明同时运行两个测试运行程序而不实现一个新的混合测试运行程序是多么容易
感谢Adam,现在我有了一个很好的工作代码:
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())中使用它代码>:
通常,这是问题的潜在原因,因为您正在构造函数中调用非私有、非final方法。对于测试用例,它可能是可接受的
稍微走开一点,我想看看这个MyClass
对象的职责是明智的。它不是做得太多了吗,因此很难测试和交互?这通常会导致“难以模仿”综合症。谢谢,这看起来是个好办法。这是单元测试的标准吗MyClass
是一个util类。虽然做的不多,但有许多相同函数的变体(例如,1、2或3个参数的变体),因此我不愿意对它们进行模拟。有人可能会认为多参数接口膨胀会增加问题。但如果没有看到来源,就很难明确回答。我想问另一个问题,MyClass
是否做了很多事情:例如,给定数据库配置+给定服务器配置+给定应用程序配置?如果是这样,它可以被分成三个单独的实体,只有通过接口才能看到。那么他们应该更容易被嘲笑。
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
}
}