2012-01-06 317 views
1

我想單元測試下面的方法如何使用thenAnswer與方法,該方法返回void

public void addRecord(Record record) 
{ 
    Myclass newObj = new Mycalss(); 
    // It creates newObj object, set some values using record object. 
    // and it adds the newObj in daatbase. 
    dataReqDao.persist(newObj); 
}  

我都嘲笑dataReqDao.persist方法,但我怎麼能驗證是否正確的值複製到newObj對象?我想獲得newObj對象。

我認爲thenAnswer將是檢索newObj ie方法參數但不知道如何使用它返回void的方法的方法。

更新:
我試圖

doAnswer(new Answer<Myclass>() { 
       public Myclass answer(InvocationOnMock invocation) { 
        Object[] args = invocation.getArguments(); 
        return (Myclass)args[0]; 
       } 

     }).when(dataReqDao.persist(any(Myclass.class))); 

編輯:
它應該是(感謝大衛)

doAnswer(new Answer<Myclass>() { 
        public Myclass answer(InvocationOnMock invocation) { 
         Object[] args = invocation.getArguments(); 
         return (Myclass)args[0]; 
        } 

      }).when(dataReqDao).persist(any(Myclass.class)); 
+0

在您的更新,括號內是在錯誤的地方。我不確定這是不是你的錯誤的原因,因爲其餘部分看起來不錯。所以它應該是'doAnswer(...).when(dataReqDao).persist(...);'這有幫助嗎? – 2012-01-10 22:56:41

+0

@David:謝謝大衛。其實我糾正了,但忘記更新我的問題。 – xyz 2012-01-11 05:45:41

回答

5

您可以創建自定義argument matcher,將檢查的領域該對象,或使用argument captor來捕獲該對象進一步檢查。

例如,如下:

ArgumentCaptor<Myclass> c = ArgumentCaptor.forClass(Myclass.class); 
verify(dateReqDao).persist(c.capture()); 
Myclass newObj = c.getValue(); 

... // Validate newObj 
+0

我試過你的建議。請檢查我的編輯。 – xyz 2012-01-06 09:53:19

+0

@Ajinkya:更新 – axtavt 2012-01-06 10:14:34

+0

這不會執行一個聰明的測試,因爲ArgumentCaptor在調用時沒有捕獲該對象的狀態,而只是objectId。所以即使你在dao調用之後在你的方法中使用了setter,你的測試也會是綠色的。但是一個好的測試應該會隨着每個功能變化而失敗我寫了我的建議作爲對這篇文章的回答。 – akcasoy 2015-04-10 07:57:38

0
Myclass newObj = new Myclass(); 

那行我感到困擾。如果你正在使用依賴注入,你應該讓你的工廠向你發送一個對象的實例。然後,當你創建你的單元測試時,你可以讓測試工廠發送一個MyClass的模擬實例,單元測試也可以訪問它。然後你可以使用axtavt的捕獲器來看它是否真的做了它應該做的事情。單元測試沒有什麼錯,就像你做的那樣,只是因爲你知道它傳入了一個這種類型的對象,所以any()是有點弱的 - 在測試中你想知道的是對象是你的目標之一,並沒有被修改。

1

您需要thenAnswer(或然後,我個人比較喜歡),使其在方法調用的時間,讓您可以斷言/驗證值的方法。

when(dataReqDao.persist(newObj)).then(new Answer<Void>() { 
     @Override 
     public Void answer(final InvocationOnMock invocation) { 
      Myclass newObjActual = (Myclass) invocation.getArguments()[0]; 

      // Control 
      assertEquals(..., newObjActual.getX()); 
      assertEquals(..., newObjActual.getY()); 
      return null; 
     } 
    }); 

// Run Test 
x.addRecord(record); 

這裏是一個詳細的解釋:https://akcasoy.wordpress.com/2015/04/09/the-power-of-thenanswer/(用例2)

ArgumentCaptor不以巧妙的方式測試。當你改變你的方法是這樣的:

public void addRecord(Record record) 
{ 
    Myclass newObj = new Mycalss(); 
    dataReqDao.persist(newObj); 

    // first persist, than set attributes 
    newObj.setX(..); 
} 

。與捕手測試仍然運行,但是它應該會失敗。由於ArgumentCaptor在調用時不會捕獲對象的狀態,而只是捕獲objectId,因此無論您是在dao調用之前還是之後設置屬性,都無關緊要。然而,每次功能改變都會導致一次好的測試失敗。下面是我的文章正是對這種情況:

https://akcasoy.wordpress.com/2015/02/03/how-to-ensure-quality-of-junit-tests/(上面的磕碰與然後是一個更好的辦法,雖然不是一個與序方法)

相關問題