在mockito中验证的想法是什么?我何时应该使用它

时间:2016-05-29 15:13:48

标签: unit-testing mocking mockito

我知道 Mockito.verify()用于确保使用必需参数调用mock方法。但我不明白这个意图。我经常看到类似的测试:

public class UserDAO {
    public long create(User user) {
        //...
    }
}

public class UserService {
    private UserDAO userDAO;

    public UserService(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    public long createUser(User user) {
        return userDAO.create(user);
    }
}

public class UserServiceTest {
    @Test
    public void testCreateUser() {
        UserDAO userDAO = mock(UserDAO.class);
        when(userDAO.create(any(User.class))).thenReturn(anyLong());

        UserService = new UserService(userDAO);
        User user = new User("John Smith");
        userService.createUser(user);

        verify(userDAO).create(user);
    }
}

测试验证在调用 UserService createUser 方法时,将调用 UserDAO create 方法。看起来很荒谬。如果我改变 UserService 的实现方式,它不会调用 UserDAO 的方法,即使实现正确,我的测试也会失败。

我承认在某些情况下可能需要验证方法是否被严格调用,但这种情况并不常见。

我很可能不理解验证的想法,而且它不是特定于mockito的功能。你能用简单的语言解释它吗?什么时候使用它真的有意义。

2 个答案:

答案 0 :(得分:2)

verify()方法是一种用于进行白盒测试的工具。但是,这不是您要测试的实际实现,而是测试,是否将某种消息(方法调用)发送到底层,或者更确切地说,指定在测试中执行代码时使用API​​

测试通常包括以下步骤:

  • 准备输入(输入参数,环境,(模拟)系统等),
  • 调用代码进行测试
  • 将实际结果(输出参数,环境变化)与预期结果(一组假设)进行比较

但预期结果不一定是某些输出数据,而是环境的一些变化。但是,如果您已经模拟了需要定义的环境,那么环境如何受到代码的影响,并且通常可以通过API来访问环境(或其他组件)。

我们以create方法为例。该方法没有返回值,但假设是在底层数据层(环境)上创建了数据集。当您模拟数据层时,如果没有存储,您将如何验证是否已存储某些数据?因此,假设没有其他选项来存储数据(从组件的角度来看)而不是调用create方法,可以假设必须调用create方法为了存储数据。因此verify(yourComponent).create()证明代码的执行是正确的。当然,这需要知道使用某个API(提供create方法),因此它是一种白盒测试。

还有其他用例:

  • 调用次数(即通过10项,假设添加了10项: verify(list, times(10)).add(any(Item.class))

  • 捕获参数,即断言某个转换发生或正确的参数传递,并且您需要访问参数

    ArgumentCaptor<ExpectedType> captor = ArgumentCaptor.forClass(ExpectedType.class); verify(theApi).apiMethod(captor.capture()); ExpectedType passedParam = captor.getValue();

  • 验证方法是否已调用 (即在某些条件下,结合正面测试)

  • 验证已调用某些参数的方法(=已发送特定消息):verify(subject).method(eq("param1"), eq("param2"))

但是所有归结为指定使用API​​以指定预期将哪些消息发送到另一个组件或系统,并 NOT 以指定测试中的每一行实现(这将是毫无意义的。)

答案 1 :(得分:0)

这个UserServiceTest的重点是测试它的实现。所以是的,您确实要验证是否确实调用了create接口的UserDAO方法。