前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mockito框架Mock Void方法

Mockito框架Mock Void方法

作者头像
FunTester
发布2020-08-10 15:46:00
9.9K0
发布2020-08-10 15:46:00
举报
文章被收录于专栏:FunTester

在编写代码时,总是有方法返回void,并且在某个测试用例需要模拟void方法。那么我们如何去做呢?让我们一起在下面的内容中使用Mockito完成这个需求。

  • Mockito是用于编写单元测试的最著名的模拟框架之一。

为什么模拟void方法

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

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

代码语言:javascript
复制
public UserService{

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

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

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

如何在Mockito中模拟void方法

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

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

使用doNothing()

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

在测试用例中,对于模拟对象的每种方法,doNothing是默认行为。因此,如果不想验证参数,则使用doNothing是完全可以的。

doNothing()用于void方法的Demo

代码语言:javascript
复制
@Test
public void test001() {
   doNothing().when(mockedUserRepository).updateName(anyLong(),anyString());
 
   userService.updateName(1L,"FunTester");
     
   verify(mockedUserRepository, times(1)).updateName(1L,"FunTester");
}

不对空方法使用doNothing()

代码语言:javascript
复制
@Test
public void test002() {
 
   userService.updateName(1L,"FunTester");
     
   verify(mockedUserRepository, times(1)).updateName(1L,"FunTester");
}

使用doNothing()进行参数捕获的示例

代码语言:javascript
复制
@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:

代码语言:javascript
复制
@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

代码语言:javascript
复制
@Test(expected = InvalidParamException.class)
public void testUpdateNameThrowExceptionWhenIdNull() {
   doThrow(new InvalidParamException())
      .when(mockedUserRepository).updateName(null,anyString();
   userService.updateName(null,"FunTester");
}

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

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

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

代码语言:javascript
复制
@Test
public void testUpdateNameCallRealRepositoryMethod() {
 
   doCallRealMethod().when(mockedUserRepository).updateName(anyLong(), anyString());
  
   userService.updateName(1L,"真实调用方法");
  
   verify(mockedUserRepository, times(1)).add(1L,"真实调用方法");
}

  • 公众号FunTester首发,更多原创文章:FunTester430+原创文章,欢迎关注、交流,禁止第三方擅自转载。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FunTester 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么模拟void方法
  • 如何在Mockito中模拟void方法
    • 使用doNothing()
      • 将doAnswer()用于void方法
        • 使用doThrow()引发异常
          • 使用doCallRealMethod()进行真实方法调用
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档