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

Mockito 3.5+替代PowerMockito的whenNew功能实现问题

从PowerMockito的whenNew迁移到Mockito 3.5+的解决方案

针对你迁移时遇到的两个问题,直接给出具体实现方案:

问题1:替换内部创建的ArrayList为外部实例

Mockito的mockConstruction支持通过自定义Answer控制构造时返回的对象,直接返回你外部创建的实例即可实现原whenNew的替换逻辑。

示例代码:

// 外部创建你要指定的ArrayList实例
List<String> targetList = new ArrayList<>();
targetList.add("init-item");

// 在try-with-resources块内拦截ArrayList的构造(仅块内生效)
try (MockedConstruction<ArrayList> mockedList = mockConstruction(ArrayList.class, 
        (context, settings) -> targetList)) {
    
    // 执行被测方法
    someService.doStuff();
    
    // 验证外部实例的变化,比如检查是否新增了预期元素
    assertThat(targetList).contains("expected-new-item");
}

问题2:解决mockConstruction默认不调用真实构造导致的NPE

默认情况下mockConstruction会创建空壳mock对象,不执行真实构造逻辑。要调用真实构造并保留实例正常功能,有两种方式:

方式1:返回真实实例

直接在Answer中调用类的真实构造方法,返回真实对象:

try (MockedConstruction<ArrayList> mockedList = mockConstruction(ArrayList.class, 
        (context, settings) -> new ArrayList<>())) {
    
    someService.doStuff();
    
    // 获取内部创建的真实实例并验证
    ArrayList<String> constructedList = mockedList.constructed().get(0);
    assertThat(constructedList).hasSize(2);
}

方式2:返回Spy实例(兼顾真实方法调用和行为验证)

如果需要同时验证实例的方法调用(比如add方法被调用次数),可以返回spy包装的真实实例:

try (MockedConstruction<ArrayList> mockedList = mockConstruction(ArrayList.class, 
        (context, settings) -> {
            ArrayList<String> realList = new ArrayList<>();
            return spy(realList); // 用spy包装真实实例
        })) {
    
    someService.doStuff();
    
    ArrayList<String> constructedSpy = mockedList.constructed().get(0);
    // 验证方法调用行为
    verify(constructedSpy, times(2)).add(anyString());
    // 验证真实数据
    assertThat(constructedSpy).containsAll(List.of("a", "b"));
}

关键区别说明

和PowerMockito的whenNew全局拦截不同,Mockito的mockConstruction通过try-with-resources实现作用域控制,避免全局mock带来的测试污染,更符合现代测试的隔离原则。

内容的提问来源于stack exchange,提问作者Jovan Perovic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:42:22