使用Mockito的Mock Void方法

本文详细介绍了如何使用Mockito模拟Java中的Void方法,包括使用doNothing()忽略调用,doAnswer()执行运行时操作,doThrow()引发异常以及doCallRealMethod()调用真实方法。通过具体示例说明了在单元测试中这些方法的用法及其适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好! 在我们之前的博客关于thenReturn和thenAnswer模拟方法之间的区别之后 ,我们又回来了关于Mockito的另一个有趣的博客。 在这里,我们将讨论“如何用Mockito模拟无效方法”。 让我们开始吧!

在编写代码时,总是至少有一种方法返回“ void”,并且在某个时间点需要模拟“ void”方法。 那么我们如何去做呢? 让我们在下面的博客中使用Mockito一起解决这个问题。

Mockito是用于编写单元测试的最著名的模拟框架之一。 如果您不喜欢模拟,可以在模拟网站上了解更多。

为什么我们需要模拟void方法?

假设我们有一个方法。 在此方法中,我们称为另一个void方法。 现在,当您要为该方法编写测试用例时,我们如何测试void方法被调用? 另外,是否将正确的参数传递给void方法?
在这种情况下,mockito可以帮助我们。

让我们举个例子,我们有一个UserService类。 在此类中,我们有一个updateName()方法。

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

现在,我们要为UserService类编写单元测试并模拟userRepository。
但是,在此测试用例中,我们唯一需要验证的是使用正确的参数集调用了userRepository中的updateName()方法。
为此,我们需要模拟updateName()方法,捕获参数并验证参数。

这里要注意的最重要的一点之一是,我们不能仅仅使用Mockito的when-then机制来模拟void方法。 因为,mockito的when()方法适用于返回值,而方法无效时则不适用。

如何在Mockito中模拟void方法?

在Mockito中,我们可以使用不同的方法来调用实数方法或模拟void方法。 我们可以根据要求使用其中一个选项

  1. doNothing() :完全忽略对void方法的调用,这是默认行为
  2. doAnswer() :在调用void方法时执行一些运行时或复杂的操作
  3. doThrow()调用模拟的 void方法时引发异常
  4. doCallRealMethod() :不要模拟并调用真实方法

1)使用doNothing()

如果我们只想完全忽略void方法调用,则可以使用doNothing()。

在模拟中,对于模拟对象的每种方法,doNothing是默认行为。 因此,如果您不想验证参数,则使用doNothing是完全可选的。 在所有代码执行类似的行为之后,

将doNothing()用于void方法的示例

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

不对空方法使用doNothing()

 @Test  public void testUpdateNameWithOutDoNothingVerifyRepositoryCall() { 
    userService.updateName(1L, "void mock test" );     
    verify(mockedUserRepository, times(1)).updateName(1L, "void mock test" );  } 

使用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, "void mock test" );     
    assertEquals(1L, idCapture.getValue()); 
    assertEquals( "void mock test" , nameCapture.getValue());  } 

2)将doAnswer()用于void方法

如果我们不想调用真实方法,则需要执行一些运行时操作,请使用doAnswer。

让我们以doAnswer为例,使用doAnswer打印并验证参数

 @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( "void mock test" , name); 
       return null;  }).when(mockedUserRepository).updateName(anyLong(),anyString()); 
    userService.updateName(1L, "void mock test" ); 
    verify(mockedUserRepository, times(1)).updateName(1L, "void mock test" );  } 

3)使用doThrow()引发异常

如果要在调用方法时引发异常,则可以使用嘲笑的doThrow()方法。

让我们举一个例子,当使用null id调用updateName()方法时,我们将引发InvalidParamException。

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

4)使用doCallRealMethod()进行真实方法调用

有时有必要从模拟对象中调用真实方法,在这种情况下,我们需要使用doCallRealMethod(),因为doNothig()是默认行为。

在以下示例中,即使是模拟对象,也会调用userRepository中的真实方法。

 @Test  public void testUpdateNameCallRealRepositoryMethod() { 
    doCallRealMethod().when(mockedUserRepository).updateName(anyLong(), anyString());  
    userService.updateName(1L, "calling real method" );  
    verify(mockedUserRepository, times(1)).add(1L, "calling real method" );  } 

快速阅读

翻译自: https://www.javacodegeeks.com/2020/06/mock-void-method-with-mockito.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值