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 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): 验证方法至多被执行的次数

你可能感兴趣的:(Verifying方法调用)