如何在Java Mockito中为Map<String,自定义类>创建参数捕获器?
解决Mockito捕获泛型Map参数的"Cannot select from parametrized type"错误
你遇到的这个问题是Java泛型类型擦除导致的——运行时JVM会抹去泛型的具体类型信息,所以Map<String, CompoundClass>.class这种写法根本不合法,编译器自然会报错。下面给你两种正确声明和初始化泛型Map参数捕获器的方法:
方法1:手动声明并强制类型转换
你可以先创建针对Map原始类型的捕获器,再强制转换为你需要的泛型类型,记得加上@SuppressWarnings("unchecked")来抑制未检查转换的警告:
@Test @SuppressWarnings("unchecked") void testDoSomething() { SubClass sb = mock(SubClass.class); Example ex = new Example(sb); // 先创建原始类型的捕获器,再强制转换为目标泛型类型 ArgumentCaptor<Map<String, CompoundClass>> argCaptor = (ArgumentCaptor<Map<String, CompoundClass>>) ArgumentCaptor.forClass(Map.class); ex.doSomeThing(); verify(sb).doSomeThingSubClass(argCaptor.capture()); // 现在可以正常获取捕获的参数并访问内部属性 System.out.println(argCaptor.getValue().get("x").a); }
方法2:使用@Captor注解(更优雅)
Mockito提供了@Captor注解,配合Mockito的初始化机制,可以自动处理泛型类型,不需要手动转换:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; class ExampleTest { @Mock private SubClass sb; @Captor private ArgumentCaptor<Map<String, CompoundClass>> argCaptor; private Example ex; @BeforeEach void setUp() { // 初始化Mockito注解,让@Mock和@Captor生效 MockitoAnnotations.openMocks(this); ex = new Example(sb); } @Test void testDoSomething() { ex.doSomeThing(); verify(sb).doSomeThingSubClass(argCaptor.capture()); System.out.println(argCaptor.getValue().get("x").a); } }
补充说明
- 如果你用的是JUnit 4,只需要把
@BeforeEach换成@Before,并且在测试类上加上@RunWith(MockitoJUnitRunner.class),就不需要手动调用MockitoAnnotations.openMocks(this)了。 - 两种方法都能解决你的问题,推荐用
@Captor注解的方式,代码更简洁,也避免了强制类型转换的警告。
内容的提问来源于stack exchange,提问作者Riko
相关产品推荐
相关产品推荐

