ArgumentCaptor用于捕获实际调用参数以验证内容,需用@Captor注解或forClass()初始化,在verify中调用capture()捕获,再通过getValue()或getAllValues()断言;不可用于stub,须确保签名一致且不混用matcher。

在 Mockito 中,ArgumentCaptor 用于捕获被测代码调用依赖对象方法时传入的实际参数,方便后续断言其值是否符合预期。它不适用于验证调用次数或行为,而是专注“参数内容是否正确”。
1. 声明和初始化 ArgumentCaptor
必须使用 @Captor 注解或 ArgumentCaptor.forClass() 创建实例,并确保在 @Before 或测试方法中完成初始化(尤其用注解时需配合 MockitoAnnotations.openMocks(this))。
- 推荐用注解方式(简洁、不易漏):
@ExtendWith(MockitoExtension.class) // JUnit 5 推荐
class UserServiceTest {
@Mock
private EmailService emailService;
@Captor
private ArgumentCaptor
@Test
void shouldSendEmailWithCorrectSubject() {
// ... 执行被测逻辑,如 userService.register(user)
verify(emailService).sendEmail(stringCaptor.capture(), anyString());
assertEquals("Welcome!", stringCaptor.getValue());
}
}
```
2. 在 verify 中调用 capture() 捕获参数
把 captor.capture() 当作普通参数传给 verify(mock).method(...),Mockito 会在匹配到该次调用时自动保存对应位置的实参。
- 只能捕获 已发生的真实调用,不能用于 stub(
when(...).thenReturn()) - 若方法有多个同类型参数,需明确放在对应位置,例如:
verify(repo).save(captor.capture())捕获第一个参数;若想捕获第二个 String 参数,就写成verify(repo).update(anyLong(), captor.capture()) - 支持泛型:如
ArgumentCaptor<list>></list>、ArgumentCaptor<map object>></map>
3. 获取捕获的值并断言
捕获后通过 getValue()(单次调用)或 getAllValues()(多次调用)获取参数,再用 JUnit 断言其内容。
立即学习“Java免费学习笔记(深入)”;
-
getValue():只返回最后一次匹配调用的参数,如果 verify 匹配了 0 次会抛IllegalStateException -
getAllValues():返回List,适合验证调用多次且参数不同的情形 - 对复杂对象建议用
assertThat(...).usingRecursiveComparison()或检查关键字段,而非直接equals
4. 注意事项和常见坑
- 不要在 stub 中用
captor.capture()—— 它只在verify中生效 - 确保
verify的方法签名与实际调用完全一致(参数类型、顺序、数量),否则捕获失败 - 使用
@Captor时,必须启用 Mockito 扩展(JUnit 5)或手动初始化(MockitoAnnotations.initMocks(this)for JUnit 4) - 避免在同一个
verify中混用captor.capture()和eq(value)等 matcher,可能导致匹配不稳定;优先全用 matcher 或全用 capture


















