mockito 的 verify() 方法用于验证被测代码中是否调用了 mock 对象上的特定方法,以及调用时的参数是否符合预期。核心做法是:先创建或注入 mock 对象,执行被测逻辑,然后使用 verify(mock).method(args) 确认调用发生;若需检查次数、顺序或排除调用,可配合 times(n)、inorder() 或 never() 等验证模式。默认情况下,verify 只关心“是否被调用”,不关心返回值(返回值在打桩时已确定)。

如何验证方法被调用且参数匹配?
要验证方法被调用并检查传入的参数,直接使用 verify(mock).method(expectedArg) 即可。如果参数是复杂对象,建议使用 argThat(new ArgumentMatcher()) 进行自定义匹配,或者使用 eq() 来精确匹配值。以下是一个完整的示例,演示如何验证一个服务类调用了依赖的 DAO 层方法,并传入了正确的用户 ID。
import static org.mockito.Mockito.*;
public class UserServiceTest {
@Mock
private UserDao userDao;
@InjectMocks
private UserService userService;
@Test
public void testVerifyMethodCallWithArgs() {
// 1. 准备数据
Long userId = 1001L;
String userName = "Alice";
// 2. 执行被测方法
userService.registerUser(userId, userName);
// 3. 验证调用
// 验证 userDao.save 被调用了一次,且第一个参数是 userId
verify(userDao, times(1)).save(eq(userId), eq(userName));
// 如果只想验证调用了 save 方法,不关心具体参数,可以这样写:
// verify(userDao).save(any(), any());
}
}
运行上述测试,如果 userService.registerUser 内部没有调用 userDao.save,或者传入的参数与 eq() 中定义的不一致,测试将失败并抛出 Wanted but not invoked 或 Argument(s) differ 异常。

如何验证方法未被调用或调用多次?
在某些场景下,我们需要确保某些副作用方法没有被触发,或者某个方法被重复调用了特定次数。使用 verify(mock, never()) 可以验证方法从未被调用;使用 verify(mock, times(n)) 可以验证方法被调用了恰好 n 次。这对于验证缓存失效、重试机制或避免重复操作非常有用。下面的例子展示了如何验证一个清理方法在特定条件下未被调用,以及在循环逻辑中被调用了多次。
import static org.mockito.Mockito.*;
public class OrderProcessorTest {
@Mock
private NotificationService notificationService;
@InjectMocks
private OrderProcessor orderProcessor;
@Test
public void testVerifyNeverAndTimes() {
// 场景1:验证方法未被调用
orderProcessor.processValidOrder();
verify(notificationService, never()).sendAlert(anyString());
// 重置 mock 状态以便进行下一次验证
reset(notificationService);
// 场景2:验证方法被调用多次
orderProcessor.batchProcessOrders(); // 假设内部循环调用了 sendAlert 3 次
verify(notificationService, times(3)).sendAlert(anyString());
}
}
如果 processValidOrder 意外调用了 sendAlert,never() 验证将失败。同样,如果 batchProcessOrders 只调用了 2 次或 4 次,times(3) 也会报错。这种严格的计数验证有助于捕捉逻辑回归错误。

如何验证方法调用的顺序?
当多个 Mock 方法的调用顺序对业务逻辑至关重要时,可以使用 InOrder 验证器。它允许你按照特定的顺序断言一系列方法的调用。注意,InOrder 只能验证指定的方法按顺序调用,不能验证其他未指定方法的插入。以下代码演示了如何在订单处理流程中验证“扣库存”必须在“发通知”之前执行。
import static org.mockito.Mockito.*;
public class OrderFlowTest {
@Mock
private InventoryService inventoryService;
@Mock
private EmailService emailService;
@InjectMocks
private OrderService orderService;
@Test
public void testVerifyCallOrder() {
// 执行逻辑
orderService.placeOrder();
// 创建 InOrder 验证器,传入需要验证顺序的 Mock 对象
InOrder inOrder = inOrder(inventoryService, emailService);
// 验证调用顺序:先扣库存,再发邮件
inOrder.verify(inventoryService).deductStock(anyLong());
inOrder.verify(emailService).sendConfirmation(anyString());
// 如果实际执行顺序反过来,这里会抛出 TooFewActualInvocations 或 WrongArgumentType 等异常
}
}
通过 inOrder.verify() 链式调用,我们可以精确控制验证的时间线。这确保了关键的业务步骤没有因为并发修改或重构而颠倒顺序,从而维持系统的一致性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











