You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:33:17