2014-07-07 33 views
1

我有,例如,這個類:是否可以調用模擬對象的方法?

public class A { 
    private List<String> list; 

    public A(B b){ 
     list = b.getList(); 
    } 

    public List<String> someMethod(){ 
     return list; 
    } 
} 

我想單元測試someMethod而不調用構造函數。我用反射來設置list

問題是我不想創建B類對象,我不能嘲笑它,因爲它會導致NPE。

所以我的問題是:

如何測試someMethod無需調用的A構造?有什麼辦法可以嘲笑A類,並且不會失去調用方法的可能性嗎?

用零參數創建構造函數不是一個解決方案。

注:想修改類的任何部分。我問是否可以在沒有添加或更改A課程中的任何內容的情況下執行此測試。

回答

4

您可以測試A類,而不調用它的構造器的Mockito。不知道我是否真的瞭解您的需求,但以下代碼適用於我。

import org.junit.Test; 
import org.springframework.test.util.ReflectionTestUtils; 

import java.util.ArrayList; 
import java.util.List; 

import static org.hamcrest.CoreMatchers.is; 
import static org.junit.Assert.assertThat; 
import static org.mockito.Mockito.mock; 
import static org.mockito.Mockito.when; 

public class ATest { 

    @Test 
    public void test() { 
     A a = mock(A.class); 
     when(a.someMethod()).thenCallRealMethod(); 
     List<String> listInA = new ArrayList<String>(); 
     ReflectionTestUtils.setField(a, "list", listInA); 
     assertThat(a.someMethod(), is(listInA)); 
    } 
} 
+0

我印象深刻。這正是我想要的。謝謝。 – nervosol

-2

我不希望創建B級對象

添加不需要一個B.

public A(B b){ 
    this(b.getList()); 
} 

/* package local */ A(List<String> list){ 
    this.list = list; 
} 

通過使構造包本地它構造函數或工廠方法可以通過相同包中的單元測試來訪問。

如何在不調用A構造函數的情況下測試someMethod?

您可以使用

A a = theUnsafe.allocateInstance(A.class); 

,但不建議這樣做,除非你有沒有其他選擇,例如反序列化。

+3

在任何情況下,您都不應該將代碼寫入生產類中,這些代碼將僅用於測試。你應該像生產場景一樣在生產環境中測試你的類,你應該只檢查類似生產的代碼路徑。 –

+1

_用零參數創建構造函數不是一個解決方案。我猜測OP對這種方法感覺相同。 – Keppil

+0

@EngineerDollery +1我同意,這是理想的,但並不是所有的項目都是理想的。 –

4

你應該嘲笑協作者到你的類 - 這意味着你可以創建一個正在測試的類的實例,並通過mock,配置爲在做方法調用時「做正確的事情」。

在你的榜樣,你要創建一個模擬B,並使用它像這樣:

@RunWith(MockitoJUnitRunner.class) 
class myTest { 
    @Mock private B b; 

    public void someMethod() { 
    doReturn(new ArrayList<String>()).when(b).getList(); 
    A a = new A(b); 
    assertEquals("result", a.someMethod().get(0)); 
    } 
} 
+0

根據A的進一步行爲,您可能需要實際返回arraylist中的某些內容,但考慮到您的示例,這應該起作用。 –

+0

問題是我根本不想模擬'B'。真正的'A'構造函數使用B和它的fileds中的多個方法。他們習慣於設置'A'字段,所以我不想嘲笑'B'中的所有內容。我想我無法做到其他任何事情。當然你的答案是正確的。 – nervosol

+1

如果它是正確的,最好打勾。現在,如果你願意,你總是可以創建一個B的實例作爲間諜(使用@Spy) - 這將允許你只嘲笑你需要的方法。然而,在編寫測試時,這是一個不變的問題 - 編寫單元測試你必須/模擬/存根協作者,否則你的測試是脆弱的。 –

相關問題