如何创建MockedConstruction<ArrayList<String>>并捕获列表元素?
如何用Mockito的MockedConstruction捕获ArrayList的添加内容
一、正确创建MockedConstruction并捕获添加内容
你的示例代码存在顺序问题:必须先配置mock的行为,再执行目标方法,不然方法执行时mock还没设置捕获逻辑,会导致捕获失败。
正确的创建方式是使用Mockito.mockConstruction()方法,推荐带配置器的版本,在每个ArrayList mock实例创建时就绑定捕获逻辑:
try (MockedConstruction<ArrayList<String>> mockedList = Mockito.mockConstruction(ArrayList.class, (mock, context) -> { // 为每个新建的ArrayList mock配置add方法的参数捕获 ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class); when(mock.add(stringCaptor.capture())).thenReturn(true); })) { // 执行目标方法,此时方法内创建的ArrayList都是mock实例 myClass.myMethod(); // 获取方法中创建的第一个ArrayList mock实例 ArrayList<String> constructedArrayList = mockedList.constructed().get(0); // 获取所有被捕获的添加内容 List<String> capturedItems = stringCaptor.getAllValues(); // 这里写断言验证,比如: assertEquals(Arrays.asList("预期元素1", "预期元素2"), capturedItems); } catch (Exception e) { fail("测试执行异常:" + e.getMessage()); }
二、用注解替代手动创建MockedConstruction
Mockito提供了@MockedConstruction注解,可以直接在测试类字段上使用,不需要手动管理try-with-resources的生命周期:
@ExtendWith(MockitoExtension.class) public class MyClassTest { // 用注解声明MockedConstruction,作用于ArrayList<String> @MockedConstruction(ArrayList.class) private MockedConstruction<ArrayList<String>> mockedArrayLists; @Test void testMyMethod() { // 获取方法中创建的ArrayList mock实例(假设只创建了一个) ArrayList<String> mockList = mockedArrayLists.constructed().get(0); // 配置参数捕获 ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class); when(mockList.add(stringCaptor.capture())).thenReturn(true); // 执行目标方法 myClass.myMethod(); // 验证捕获结果 List<String> captured = stringCaptor.getAllValues(); // 断言逻辑... } }
如果需要批量配置所有mock实例的行为,还可以自定义初始化类绑定到注解上:
@ExtendWith(MockitoExtension.class) public class MyClassTest { // 指定初始化类,自动为每个mock实例配置捕获逻辑 @MockedConstruction(value = ArrayList.class, onConstruction = ListMockInitializer.class) private MockedConstruction<ArrayList<String>> mockedArrayLists; @Test void testMyMethod() { myClass.myMethod(); // 获取捕获的内容(需要把captor提升为类变量或者用其他方式传递) List<String> capturedItems = ListMockInitializer.stringCaptor.getAllValues(); // 断言逻辑... } // 自定义初始化类,实现MockInitializer接口 static class ListMockInitializer implements MockedConstruction.MockInitializer<ArrayList<String>> { // 静态captor,方便测试方法中获取捕获结果 static ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class); @Override public void prepare(ArrayList<String> mock, MockedConstruction.Context context) { when(mock.add(stringCaptor.capture())).thenReturn(true); } } }
关于类似ArgumentCaptor的构造捕获工具
Mockito没有专门的"ConstructionCaptor"类,但通过上述MockedConstruction结合ArgumentCaptor的方式,完全可以实现捕获构造的实例以及实例上的方法调用参数。
内容的提问来源于stack exchange,提问作者berger-devel
相关产品推荐
相关产品推荐

