Mockito框架Mock Void方法


在編寫代碼時,總是有方法返回void,並且在某個測試用例需要模擬void方法。那么我們如何去做呢?讓我們一起在下面的內容中使用Mockito完成這個需求。

  • Mockito是用於編寫單元測試的最著名的模擬框架之一。

為什么模擬void方法

假設我們有一個方法A,在此方法中,使用了另一個void方法B。現在,當要為該方法編寫測試用例時,我們如何測試B方法被調用?另外,是否將正確的參數傳遞給B方法?在這種情況下,Mockito可以幫助我們解決這個問題。

讓我們舉個例子,我們有一個UserService類。在此類中,我們有一個updateName()方法。

public UserService{

   public void updateName(Long id, String name){
      userRepository.updateName(id, name);
   }
}

現在,我們要為UserService類編寫單元測試並模擬userRepository。但是,在此測試用例中,我們唯一需要驗證的是使用正確的參數集調用了userRepository中的updateName()方法。為此,我們需要模擬updateName()方法,捕獲參數並驗證參數。

這里要注意的最重要的是,我們不能僅僅使用Mockitowhen-then機制來模擬void方法。因為,Mockitowhen()方法適用於返回值,而方法返回值是void時則不適用。

如何在Mockito中模擬void方法

Mockito中,我們可以使用不同的方法來調用實例方法或模擬void方法。根據要求使用其中一個選項:

  • doNothing():完全忽略對void方法的調用,這是默認
  • doAnswer():在調用void方法時執行一些運行時或復雜的操作
  • doThrow():調用模擬的 void方法時引發異常
  • doCallRealMethod():不要模擬並調用真實方法

使用doNothing()

如果我們只想完全忽略void方法調用,則可以使用doNothing()

在測試用例中,對於模擬對象的每種方法,doNothing是默認行為。因此,如果不想驗證參數,則使用doNothing是完全可以的。

doNothing()用於void方法的Demo

@Test
public void test001() {
   doNothing().when(mockedUserRepository).updateName(anyLong(),anyString());
 
   userService.updateName(1L,"FunTester");
     
   verify(mockedUserRepository, times(1)).updateName(1L,"FunTester");
}

不對空方法使用doNothing()

@Test
public void test002() {
 
   userService.updateName(1L,"FunTester");
     
   verify(mockedUserRepository, times(1)).updateName(1L,"FunTester");
}

使用doNothing()進行參數捕獲的示例

@Test
public void testUpdateNameUsingArgumentCaptor() {
 
   ArgumentCaptor<Long> idCapture = ArgumentCaptor.forClass(Long.class);
   ArgumentCaptor<String> nameCapture = ArgumentCaptor.forClass(String.class);
   doNothing().when(mockedUserRepository).updateName(idCapture.capture(),nameCapture.capture());
  
   userService.updateName(1L,"FunTester");
     
   assertEquals(1L, idCapture.getValue());
   
   assertEquals("FunTester", nameCapture.getValue());
}

將doAnswer()用於void方法

如果我們不想調用真實方法,則需要執行一些運行時操作,請使用doAnswer()

下面是使用doAnswer()打印並驗證參數的Demo:

@Test
public void testUpdateNameUsingDoAnswer() {
   doAnswer(invocation -> {
      long id = invocation.getArgument(0);
      String name = invocation.getArgument(1);
      System.out.println("called for id: "+id+" and name: "+name);
 
      assertEquals(1L, id);
      assertEquals("FunTester", name);
 
      return null;
}).when(mockedUserRepository).updateName(anyLong(),anyString());
 
   userService.updateName(1L,"FunTester");
   verify(mockedUserRepository, times(1)).updateName(1L,"FunTester");
}

使用doThrow()引發異常

如果要在調用方法時引發異常,則可以使用嘲笑的doThrow()方法。

讓我們舉一個例子:當使用null作為id調用updateName()方法時,我們將引發InvalidParamException

@Test(expected = InvalidParamException.class)
public void testUpdateNameThrowExceptionWhenIdNull() {
   doThrow(new InvalidParamException())
      .when(mockedUserRepository).updateName(null,anyString();
   userService.updateName(null,"FunTester");
}

使用doCallRealMethod()進行真實方法調用

有時有必要從模擬對象中調用真實方法,在這種情況下,我們需要使用doCallRealMethod(),因為doNothig()是默認行為。

在以下示例中,即使是模擬對象,也會調用userRepository中的真實方法。

@Test
public void testUpdateNameCallRealRepositoryMethod() {
 
   doCallRealMethod().when(mockedUserRepository).updateName(anyLong(), anyString());
  
   userService.updateName(1L,"真實調用方法");
  
   verify(mockedUserRepository, times(1)).add(1L,"真實調用方法");
}

  • 公眾號FunTester首發,更多原創文章:FunTester430+原創文章,歡迎關注、交流,禁止第三方擅自轉載。

熱文精選


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM