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,"真实调用方法");
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值