簡體   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