2012-09-19 88 views
0

該場景是我正在嘗試驗證域對象並將驗證消息存儲在另一個對象中。類是Validator和方法的樣子:Mockito:如何獲得參數的狀態

public void validate (Domain domain, ValidationInfo info) 

而且ValidationInfo對象有:

List<String> messages = new ArrayList<String> messages() 

Validator類是從一個服務類調用。無論域對象的驗證失敗,失敗消息都將存儲在ValidationInfo類的列表中。

在測試用例的一個服務測試類我寫了下面的測試驗證失敗:

@Test 
public void testvalidation() throws Exception { 
    Domain domain = createDomainWithInvalidData(); 
    service.create (domain); 
    verify(mockValidator).validate(domain, validationInfo); 
    assertFalse (validationInfo.getMessages().isEmpty()); 

現在,我要的是從validationInfo對象獲取失敗的消息讓我能根據它寫一些斷言。但它不起作用。

任何人都可以對此有所瞭解。

回答

0

從我收集你的單元測試service

其實有在,因爲它傳遞給的的Mockito模擬的方法,它確實定義什麼,除非你寫一個存根(given(...).willReturn(...))正從validationInfo消息是沒有意義的。即使代碼示例中的最後一個斷言也不是必需的,因爲validationInfo不會被默認的模擬行爲validate修改。

Mockito旨在測試合作者之間的互動,當您正在測試服務及其與Validator的合作時,已與您的驗證verify(...)一起完成測試。

測試是否寫在ValidationInfo消息無關與service

範圍然而,你想要的是單元測試Validator,在其中你應該寫爲驗證消息的特定測試。請看下面的代碼片段,我imaginated的ValidationInfo API的某些部分:

public class ValidatorTest { 

    Validator validator = new Validator(); // not a mock 

    @Test 
    public void when_<some_part_of_the_domain>_is_incorrect_report_validation_error() throws Exception { 
     // given 
     Domain domain = createDomainWithInvalidData(); 

     // when 
     validator.validate(domain, validationInfo); 

     // then 
     assertThat(validationInfo.getMessages()).isNotEmpty()); // not really necessary 
     assertThat(validationInfo.getLastMessage().text()).contains("<some_part_of_the_domain> is wrong"); 
    } 
} 

請注意,我用的BDD關鍵字(給定的時候,當時的)幫我寫的考驗。 Alos我使用了FestAssert庫,它提供了很好的斷言工具。

嗨,幫助。

+0

謝謝你的想法,布賴斯。你說得對,我正在測試'服務'。但出於好奇,有沒有辦法去做我以前問過的事情。如果是這樣的話。我嘗試使用'ArgumentCaptor',但它不工作。 – Subhash

0

我能夠達到我想要的東西后,我的頭幾個小時。

我們需要做的是使用mockito的doAnswer。請找到下面的代碼片段:

doAnswer(new Answer<ValidationInfo>() { 
    @Override 
    public ValidationInfo answer (InvocationOnMock invocationOnMock) throws Throwable { 
    Object [] args = invocationOnMock.getArguments(); 
    ValidationInfo vi = (ValidationInfo) args [1]; 
    vi.getMessages.add("some message"); 
    return vi; 
}}).when(validator).validate (domain, validationInfo); 

這樣我能夠把定製的失敗消息在做驗證的服務故障列表;這是測試的全部目的。

而之前的測試未通過,因爲在服務代碼中檢查了列表的大小。列表大小始終爲零,因爲verify只會驗證方法是否被調用,但不會實際更改對象的狀態。

希望這會有所幫助。如果有更好的方法來實現這一點,請評論。

+0

你正在過度複雜自己,加上斷言'assertFalse(validationInfo.getMessages()。isEmpty());'不測試你的生產代碼,但你剛寫的答案實際上增加了一些消息。這種行爲看起來像你期望從驗證者那裏得到的,這種行爲應該在他自己的單元測試中進行測試。無論如何,如果你的服務在'validationInfo'上失敗,那麼你必須這樣做,或者你可以設計不同的代碼,比如'validatioInfo.addFrom(validator.validate(domain))'或者validator是一個接口'validationInfo.validate (domain,validator1)'等。 – Brice

+0

感謝Brice對你的投入......事實上,正如你所說的那樣,由於服務在'validationInfo'上失敗,我必須這樣做。你說得對,我可以以不同的方式進行設計。我可以讓'validate'方法返回'validationInfo'。然後我可以寫一個存根'當(...)。然後返回(...)'。再次感謝您的建議。 – Subhash