我知道 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的功能。你能用简单的语言解释它吗?什么时候使用它真的有意义。
答案 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
方法。