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
不会被初始化,因此不会调用real
getMyObject()
方法

但是这种解决方法给我带来了另一个头疼的问题,因为这意味着我将不得不对
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
  }

}