2017-07-31 149 views
3

在Java中,我想寫的方法測試(簡單的代碼片段):嘲諷的getClass()

public class MyClass { 
    private static final Set<Class> SOME_SET = new HashSet<Class>(Arrays.asList(Foo.class, Bar.class)); 

    public boolean isValid(Class clazz){ 
     return SOME_SET.contains(clazz); 
    } 
} 

與下面的測試

import static org.mockito.Mockito.when; 
import org.mockito.Mockito; 

public class MyClassTest { 
    @Test 
    public void isValid_Foo_returnsTrue(){ 
     Foo foo = Mockito.mock(Foo.class); 
     MyClass target = new MyClass(); 
     assertTrue(target.isValid(foo)); 
    } 
} 

的問題是,在嘲笑類Foo,foo.getClass()返回帶有額外後綴的類名。事情是這樣的:因爲這個原因試驗

Foo$$EnhancerByMockitoWithCGLIB$$45508b12 

失敗,因爲SOME_SET.contains(clazz所)返回

我無法嘲笑的getClass()方法上的Foo:

Mockito.when(foo.getClass()).thenReturn(Foo.class); 

由於編譯器抱怨:(?類<捕獲#1-延伸美孚>) 方法thenReturn在type OngoingStubbing <類< capture#1 of?延伸的Foo > >不適用的參數(<類Foo >)

問題是,怎麼實現的getClass()嘲笑對象返回的值相同的getClass()真實的方法的方法(非嘲笑)對象

+0

嗯......你的問題出了什麼問題。 isValid期望一個類作爲它的參數。但是你在測試中傳遞一個對象。 –

+0

你說得對,當我簡化了這個例子時,我犯了一個錯誤。它應該是公共布爾值isValid(Object object){return 0; SOME_SET.contains(object.getClass()); } – zoran

回答

1

簡單:你不行。

請記住:a 嘲弄對象並不是真正的嘲諷類。這是東西嘲笑框架爲您創建看起來像真正的類。但你不能有兩種方法:要麼是假的要麼是真的

而在你的情況下,合理的測試看起來不一樣呢:

@Test 
public void testIsValidForInvalidClass() { 
    assertThat(target.isValid(String.class), is(false)); 
} 

@Test 
public void testIsValidForValidClass() { 
    assertThat(target.isValid(Foo.class), is(true)); 
} 

例如。在第一個地方嘲笑對象沒有意義。正如你可以容易構造和通過類的對象類!

+0

我明白了。無論如何,你搖滾:) – davidxxx

+1

大聲笑你真的讓我笑:) – davidxxx

+0

這個答案是正確的,沒有嘲笑在這裏需要,但平坦的錯誤對象不是嘲笑類的實例。像Mockito這樣的庫使用代理對象來模擬(這是動態生成的子類的實例)的事實僅僅是所述庫所採用的模擬實現方法的細節。其他庫,如PowerMock和JMockit(我自己的)在不創建這種代理的情況下使用不同的方法。 –

2

我覺得在你的場景中嘲笑Foo是沒有意義的。只需將Foo.class作爲參數傳遞即可。您正在檢查MyClass.isValid邏輯,並且您不會檢查Foo上的任何交互。

+0

+1毫無疑問,最明智的答案。很多人看到人們認爲他們需要使用嘲笑,當沒有嘲諷的測試更好的時候... –

2

Mockito.mock(Foo.class)產生一個Foo類型的對象,但不完全是Foo類。在後臺創建一個匿名代理,這是Foo的一個子類。所以,這個班是不一樣的。

對於您的isValid實現的一個注意事項是:您確實想要檢查該類,還是僅檢查該類的類型(也將接受子類isAssignableFrom)。如果你檢查類型匹配,那麼你可以用模擬類來測試你的方法。

另外,你認爲你可以以某種方式處理對象而不是類(例如isValid(object))嗎?在我看來,使用對象在OOP中比在clazz中更好。 我建議:

public boolean isValid(Object obj) { 
     return SOME_SET.stream().anyMatch(clazz -> clazz.isInstance(obj)); 
    } 
0

當初始化對象「富」,只是創建Foo類型的對象,而不是創建美孚的一個模擬的。例如,如果可能的話:

Foo foo = new Foo() 
+0

如果可能的話,這會很好,但是在現實生活中,Foo是GWT小部件,不可能是在測試中實例化,所以在測試中使用它的唯一方法是創建一個模擬。 – zoran