使用 argumentcaptor 捕获参数的核心做法是:先通过 argumentcaptor.forclass() 创建实例,用 @captor 注解或手动调用 mockito.initfields() 初始化,然后在测试中调用被 mock 的方法,最后通过 captor.getvalue() 或 captor.getallvalues() 获取实际传入的参数对象。

如何定义和初始化 ArgumentCaptor 实例
在 JUnit 4 中通常结合 @Mock 和 @Rule 使用 MockitoJUnitRunner 或 MockitoRule 来自动初始化字段;在 JUnit 5 中则需显式调用 MockitoAnnotations.openMocks(this)。定义时指定泛型类型以确保类型安全,例如 ArgumentCaptor 用于捕获字符串参数。

import static org.mockito.Mockito.*;
import static org.mockito.ArgumentMatchers.*;
import org.mockito.ArgumentCaptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class CaptorTest {
@Mock
private MyService myService;
@Test
public void testCapture() {
// 1. 定义 captor
ArgumentCaptor<string> captor = ArgumentCaptor.forClass(String.class);
// 2. 执行被测代码
myService.doSomething("hello");
// 3. 捕获参数
verify(myService).doSomething(captor.capture());
String capturedValue = captor.getValue();
// 4. 验证结果
assertEquals("hello", capturedValue);
}
}</string>
如何捕获多个调用中的不同参数值
当被 mock 的方法被多次调用时,getValue() 只返回最后一次调用的参数,而 getAllValues() 返回一个包含所有调用参数的列表。这在需要验证方法调用顺序或累积行为时非常有用。注意 getAllValues() 返回的是 List,需确保列表大小符合预期后再访问具体元素。

import static org.mockito.Mockito.*;
import org.mockito.ArgumentCaptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
@RunWith(MockitoJUnitRunner.class)
public class MultiCallCaptorTest {
@Mock
private MyService myService;
@Test
public void testMultipleCalls() {
ArgumentCaptor<string> captor = ArgumentCaptor.forClass(String.class);
// 模拟多次调用
myService.doSomething("first");
myService.doSomething("second");
myService.doSomething("third");
// 捕获所有参数
verify(myService, times(3)).doSomething(captor.capture());
List<string> allValues = captor.getAllValues();
// 验证所有值
assertEquals(3, allValues.size());
assertEquals("first", allValues.get(0));
assertEquals("second", allValues.get(1));
assertEquals("third", allValues.get(2));
// 仅获取最后一个值
assertEquals("third", captor.getValue());
}
}</string></string>
捕获复杂对象参数时的注意事项
当捕获自定义对象(如 DTO 或实体类)时,ArgumentCaptor 捕获的是对象的引用而非副本。这意味着如果在后续代码中修改了该对象,捕获的值也会随之改变。为避免此问题,应在捕获后立即深拷贝对象或使用不可变对象。此外,若对象包含 null 值或特殊类型,需确保泛型声明与实际类型一致,否则可能引发 ClassCastException。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











