2012-11-21 16 views
2

我正在使用Mockito來測試我的課程。我正在嘗試使用Deep存根,因爲我沒有在Mockito的另一個模擬對象中注入模擬。Mockito - 深鑿

class MyService{ 

    @Resource 
    SomeHelper somehelper; 

    public void create() 
    { 
     //.... 
     somehelper.invokeMeth(t); 
    } 
} 

class SomeHelper{ 
    @Resource 
    private WebServiceTemplate webServiceTemplate; 

    public void invokeMeth(T t) 
    { 
     try{ 
      //... 
      webServiceTemplate.marshalSendAndReceive(t); 
     }catch (final WebServiceIOException e) { 
      throw new MyAppException("Service not running"); 
     } 
    } 
} 

現在我試圖單元測試MyService類的create()方法。 如下

@Mock(answer = Answers.RETURNS_DEEP_STUBS) 
SomeHelper somehelper; 

當invokeMeth()方法被調用的嘲笑對象somehelper它調用在這種情況下,真正的方法我現在想的是我已經注射SomeHelper一個模擬。

when(somehelper.invokeMeth(isA(RequestObject.class))) 
    .thenCallRealMethod(); 

我期待在這種情況下webServiceTemplate不爲null。

但是我得到一個空指針異常,當代碼試圖執行行

webServiceTemplate.marshalSendAndReceive(t); 

任何線索我怎麼可以在一個模擬可以訪問了深刻的模擬對象(即模擬 - 在這種情況下webserviceTemplete模擬內部somehelper mock),然後應用when條件來拋出WebserviceIOException? 我想這樣做,以便我可以測試MyService.create()以檢查它在代碼中拋出WebServiceIOException時的行爲。

回答

3

是的,當然,你是混合真實對象和嘲笑。再加上使用thenCallRealMethod類似於部分模擬的lloks,這裏感覺不對,難怪javadoc of this method也在談論這個問題。

我definatelty應該強調你比設計明智,有一個模擬回報模擬往往是一種氣味。更確切地說,你打破了德米特法律,或不遵循告訴,不要問的原則。

任何看你的代碼我不是爲什麼代碼需要模擬WebServiceTemplate。你想單元測試MyService,我沒有看到與WebServiceTemplate的關係。相反,你應該只關注與你的幫手交互。並單元測試SomeHelper分開在那裏你將能夠檢查SomeHelperWebServiceTemplate之間的相互作用。

這裏是我所看到的東西一個小例子:

public void ensure_helper_is_used_to_invoke_a_RequestObject() { 
    // given a service that has an helper collaborator 
    ... other fixture if necessary 

    // when 
    myService.behaviorToTest(); 

    // then 
    verify(someHelperMock).invokeMeth(isA(RequestObject.class)); 
} 

怎麼那些尋找您的實際使用情況?

希望可以幫到

+0

謝謝brice。是的,我完全同意你的看法。事情是,如果說服務不可用,這是代碼層次結構中的一層,MyService create()以特定方式處理它。我同意我可以嘲笑錯誤響應並測試相同的內容。這是正確的單元測試。實際上是在探索是否需要我們可以在另一個模擬中注入一個模擬,然後對注入的模擬應用時間 - 然後返回規則。 – Soumya

+0

@Soumya _'Was實際探索是否需要,我們可以在另一個模擬中注入一個模擬,然後對注入的模擬應用一個when-then-return規則。'_不,你不能這樣做,從技術上講這是可能的,但它會打破模擬語義,相反,你可以使用**間諜**,但請注意,在你的情況下,它可能會導致部分嘲笑。最重要的是使測試易於維護並且非常易讀(表達性但不是冗長);如果玩得太多,可能會受到影響;我曾經這樣做過,而且一塌糊塗。 – Brice

+0

非常感謝Brice。同意你。 – Soumya