简体   繁体   English

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

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

I have the following code: 我有以下代码:

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));
    }
}

The test failed with an error Could not initialise class MyStaticClass . 测试失败并显示错误Could not initialise class MyStaticClass The reason being this static class is initialising many more other class objects that are not available during test (eg database) and I do not care as you can see I am ok to return null when the method getMyObject() is called. 这个静态类的原因是初始化了许多在测试期间不可用的其他类对象(例如数据库),我不在乎你可以看到我可以在调用方法getMyObject()时返回null。

But this intention failed as well because before the doReturn(null) line is reached, the test has already failed at the spy(new MyClass()) line, in which it calls getMyObject() to initialise the private member myObject . 但是这个意图也失败了,因为在达到doReturn(null)行之前,测试已经在spy(new MyClass())行中失败了,在该行中它调用getMyObject()来初始化私有成员myObject

A workaround to the above situation is to use mock(MyClass.class) instead of spy(new MyClass()) , so that the private member myObject is not being initialised and hence not calling the real getMyObject() method. 解决上述情况的方法是使用mock(MyClass.class)而不是spy(new MyClass()) ,这样私有成员myObject就不会被初始化,因此不会调用真正的getMyObject()方法。

But this workaround creates another headache to me because that means I will have to do some configuration (even just to doCallRealMethod() ) for those heaps more methods within MyClass . 但是这个解决方法给我带来了另一个麻烦,因为这意味着我将不得不为MyClass更多方法做一些配置(甚至只是doCallRealMethod() )。

Question: is there another solution that I can still use spy on an instance of MyClass so that I can forget about configuring those heaps more methods within this class, yet I can get around the Could not initialise class MyStaticClass error? 问题:是否有另一种解决方案,我仍然可以在MyClass的实例上使用间谍,这样我就可以忘记在这个类中配置那些堆更多的方法,但是我可以绕过Could not initialise class MyStaticClass错误?

PS I can't simply just use Power Mock to mock MyStaticClass because I am already using another test runner for MyTest . PS我不能简单地使用Power Mock来模拟MyStaticClass因为我已经在为MyTest使用另一个测试运行器了。 Unless your answer can show how easy it is to run two test runners at the same time without implementing a new hybrid test runner combining both. 除非您的答案能够说明在没有实施新的混合测试运行器的情况下同时运行两个测试运行器是多么容易。


Thanks to Adam, now I have a good working code : 感谢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));
    }
}

Create a subclass of MyClass and use it in private MyClass spyMyClass = spy(new TestMyClass()); 创建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
  }

}

In general, this is a potential cause for problems, as you are calling a non-private, non-final method in your constructor. 通常,这是导致问题的潜在原因,因为您在构造函数中调用非私有的非final方法。 For the test case it might be acceptable. 对于测试用例,它可能是可以接受的。

Stepping away a bit, I guess it would be wise to take a look at responsibilities of this MyClass object. 踩了一下,我想看看这个MyClass对象的职责是明智的。 Isn't it doing too much, therefore it is hard to test and interact with? 是不是做得太多,因此很难测试和互动? That often results in "hard-to-mock" syndrome. 这通常会导致“难以模拟”的综合症。

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

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