Verifying方法调用

  在编写单元测试的时候,需要验证某些信息,或者是返回结果,或者是执行流程。一个没有任何结果验证的单元测试是没有任何意义的。对于存在返回值的方法,可以通过对返回值进行校验(使用Assert),来判断方法的逻辑正确。但是对于返回值为void的方法,或者想要校验某些mock的方法是否被调用,此时就需要使用Verify来进行验证。
  Verifying功能非常强大,在Mockito、PowerMockito等框架中都存在相应的方法。它可以检查在单元用例执行过程中某个方法是否被执行,Powermock提供了多种方式验证方法是否被调用。

一、Verify普通方法

  先来看下业务代码。

public class User {
    public boolean isNew() {
        throw new UnsupportedOperationException();
    }

    public void update() {
        throw new UnsupportedOperationException();
    }

    public void create() {
        throw new UnsupportedOperationException();
    }
}

public class UserService {
    public void saveUser(User user) {
        if (user.isNew()) {
            user.create();
            return;
        }

        user.update();
    }
}

  业务代码很简单,现在看下测试用例:

@RunWith(PowerMockRunner.class)
public class UserServiceTest {
    @Mock
    private User userMock;

    @Test
    public void shouldCreateUserIfUserIsNew() {
        PowerMockito.when(userMock.isNew()).thenReturn(true);

        UserService userService = new UserService();
        userService.saveUser(userMock);

        // Verify方法create被调用
        Mockito.verify(userMock).create();

        // Verify方法update没有被调用
        Mockito.verify(userMock, Mockito.never()).update();
    }
}

  此处saveUser方法是void的,可以验证两个逻辑,根据isNew的返回值来verify是create被调用还是update被调用。在该单元测试用例中,isNew被mock返回值为true,所以后面验证create被调用,update方法没有被调用。

二、Verify静态方法

  现在再来看一个verify静态方法的例子。业务代码:

public class Employee {
    public static void giveIncrementOf(int percentage) {
        throw new UnsupportedOperationException();
    }
}
public class EmployeeService {
    public boolean giveIncrementToAllEmployeeOf(int percentage) {
        try {
            Employee.giveIncrementOf(percentage);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

  业务代码是根据给定的百分比给员工涨工资,如果成功则返回true,否则出现异常时返回false。下面测试用例verify方法Employee.giveIncrementOf被调用。

@RunWith(PowerMockRunner.class)
@PrepareForTest({Employee.class})
public class EmployeeServiceTest {

    @Test
    public void shouldInvokeGiveIncrementOfMethod() {
        // Mock
        PowerMockito.mockStatic(Employee.class);
        PowerMockito.doNothing().when(Employee.class);
        Employee.giveIncrementOf(9);

        // Execute
        EmployeeService employeeService = new EmployeeService();
        employeeService.giveIncrementToAllEmployeeOf(9);

        // Verify
        PowerMockito.verifyStatic();
        Employee.giveIncrementOf(9);
    }
}

  首先使用verifyStatic通知Powermock现在需要验证静态方法,然后后面跟着需要验证的静态方法调用。

三、Verify方法调用顺序

  有时候想要验证多个方法是按照一定的顺序执行,比如在测试UserService.saveuser方法时,想要确保user.isNew先被调用,然后是user.create或user.update方法被调用,测试用例可以如下实现:

@Test
    public void shouldInvokeIsNewBeforeInvokingUpdate() {
        UserService userService = new UserService();
        userService.saveUser(userMock);

        InOrder inOrder = Mockito.inOrder(userMock);
        inOrder.verify(userMock).isNew();
        inOrder.verify(userMock).update();
        inOrder.verify(userMock, Mockito.never()).create();
    }

  从上面的用例中可以看出,想要验证方法的调用顺序,需要以下两点:
  1. 首先创建一个InOrder实例;
  2. 使用这个实例按照给定的顺序来验证相应的方法。给定的方法的顺序必须精确的匹配方法调用的顺序,否则会执行错误。

四、其他验证方法及模式

  Mockito和PowerMockito除了上述介绍的用法外,还提供了很多其他相关的verify方法。

//根据模式验证普通方法
public static <T> T verify(T mock, VerificationMode mode);
//根据模式验证静态方法
public static synchronized void verifyStatic(VerificationMode verificationMode);
//验证一个实例的私有方法
public static PrivateMethodVerification verifyPrivate(Object object) throws Exception;
//根据模式验证一个实例的私有方法
public static PrivateMethodVerification verifyPrivate(Object object, VerificationMode verificationMode)  throws Exception;
//验证一个类的私有方法
public static PrivateMethodVerification verifyPrivate(Class<?> clazz);
//根据模式验证一个类的私有方法
public static PrivateMethodVerification verifyPrivate(Class<?> clazz, VerificationMode verificationMode) throws Exception;

相关模式常用的有

  • Mockito.times(int n): 精确地验证执行次数
  • Mockito.atLeastOnce(): 验证方法至少被调用一次
  • Mockito.atLeast(int n): 验证方法至少被执行的次数
  • Mockito.atMost(int n): 验证方法至多被执行的次数
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,680评论 19 139
  • 1. 预备知识 如果需要往下学习,你需要先理解 Junit 框架中的单元测试。 如果你不熟悉 JUnit,请查看下...
    会飞的大象_阅读 2,813评论 0 4
  • Instrumentation介绍 Instrumentation是个什么东西? Instrumentation测...
    打不死的小强qz阅读 7,971评论 2 39
  • 我原本一直是喝白开水的,因为我始终相信,只有白开水才无毒无害。第一次喝茶也纯属偶然。清明节下午,在微信里看到一张绿...
    樱桃与狗阅读 708评论 0 0
  • #1 固执的产生论 近日可好,见字如晤。 万事清和,只觉这人世是虚张的人世,有些道理看不清,有些固执还保留。反正无...
    荒予阅读 315评论 1 9

友情链接更多精彩内容