2013-07-30 43 views
9

我想測試一個抽象類,Mockito不初始化我的成員變量。這裏有一個簡單的例子來向你展示我的問題。爲什麼Mockito跳過我的抽象類的成員變量的初始化

這是一個抽象類,初始化其「場」成員:

import java.util.ArrayList; 
import java.util.Collection; 

public abstract class Foo { 
    private final Collection field = new ArrayList(); 

    protected Foo() { 
     System.out.println("In constructor"); 
    } 

    public boolean isNull(Object o) { 
     field.add(o); 

     return o == null; 
    } 

    abstract void someAbstractMethod(); 
} 

這裏測試類:

import org.junit.Assert; 
import org.junit.Test; 
import org.mockito.Mockito; 

public class FooTest { 
    @Test 
    public void testSomething() { 
     final Foo foo = Mockito.mock(Foo.class); 

     Mockito.when(foo.isNull(Mockito.anyObject())).thenCallRealMethod(); 

     Assert.assertFalse(foo.isNull("baaba")); 
    } 
} 

當測試運行它拋出一個NPE因爲變量「字段'沒有初始化!

我在做什麼錯?

+0

不建議使用http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html#thenCallRealMethod%28%29。你想測試什麼?如果是Foo的某些方法的實現,那麼只需創建一個子類。當你想驗證行爲或存根方法調用時,使用Mockito。 –

+0

正如我對[@ david-wallace](http://stackoverflow.com/users/1081110/david-wallace)所說的,我想測試抽象類。我使用模擬的意圖是爲了防止抽象類或其接口之一發生更改時出現編譯錯誤。 – Pigelvy

回答

4

這是預期的行爲,當你嘲笑創建的實例是一個完整的模擬的東西,所以它是沒有意義的初始化字段作爲行爲是默認

除此之外,字段可以由具體或抽象類中的構造函數初始化,因爲嘲笑實例化僅僅因爲它是模擬的,繞過構造函數,所以初始化它們更加不合理。

使用mock時,試圖調用真正的方法通常是錯誤的。相反,人們應該嘲笑模擬的行爲。

Mockito.when(foo.isNull(Mockito.anyObject())).thenReturn(false); 
Assert.assertFalse(foo.isNull("baaba")); // assertion always passing 

我不知道你的實際使用情況,但也許你想要的部分模擬,具有spy。雖然這仍然被認爲是不好的做法,因爲它通常意味着您需要重構代碼以使用合成。

+0

我希望Mockito能夠做一些沒有設計的事情。正如[@ David-Wallace](http://stackoverflow.com/users/1081110/david-wallace)所討論的那樣,我將在我的測試中創建虛擬實現,如果方法被添加/刪除,我將不得不維護虛擬實現。 Thx – Pigelvy

+0

這是靜態成員的預期行爲嗎?我試過了,Mockito需要初始化靜態成員,它應該跳過初始化也是正確的? – dushyantashu

+0

@dushyantashu靜態成員在加載類時由類加載器初始化。 Mockito不會改變這一點。 – Brice

3

你似乎在嘲笑你實際試圖測試的類。這不是嘲笑的想法。你嘲笑那些超出測試範圍的類,並讓你測試的東西解除鎖定。

在這種情況下,你應該只創建一個Foo,用虛擬實現的someAbstractMethod和測試直接。據我所知,不需要任何嘲笑。

+0

確實,我想模擬我正在測試的抽象類,以便每當將新的抽象方法添加到該類(或其某個接口)時,測試不會失敗。這真的是一種不好的做法嗎? – Pigelvy

+0

我沒有足夠的經驗來制定關於什麼是「壞習慣」的法律,什麼不是。但它感覺就像使用鑿子作爲螺絲刀。這不是模擬的設計。我的直覺就是堅持測試你自己的虛擬實現,並在需要的地方添加新的方法。我猜這取決於你想多長時間向類中添加一個新的抽象方法 - 如果它經常發生,那麼Brice關於重構使用組合的觀點可能適用。但你的問題的答案是,Mockito從來沒有打算...... –

+0

...初始化其模擬領域;現在用這些知識武裝起來,然後繼續以最適合您的方式進行測試。 –

相關問題