繁体   English   中英

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

[英]Mockito spy failed because class member cannot be initialised

我有以下代码:

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错误?

PS我不能简单地使用Power Mock来模拟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());使用它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
  }

}

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

踩了一下,我想看看这个MyClass对象的职责是明智的。 是不是做得太多,因此很难测试和互动? 这通常会导致“难以模拟”的综合症。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM