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

PowerMockito.whenNew未按预期工作 构造函数Mock失效问题排查

问题根因

whenNew不生效和私有方法、Whitebox反射调用没有任何关系,核心原因是测试类中JUnit版本与PowerMock运行器不兼容:
你当前代码混用了JUnit 5(Jupiter)的注解(@Test、@BeforeEach、Assertions都来自org.junit.jupiter.api包),却使用了仅支持JUnit4的@RunWith(PowerMockRunner.class)运行器。该运行器无法识别JUnit5的测试生命周期,字节码插桩逻辑不会在正确的时机执行,自然无法拦截new关键字的实例化逻辑,最终会走真实的构造函数。

另外你代码中@PrepareForTest(AccionPSD2.class)的写法是正确的:拦截new操作时,注解里需要配置的是调用new关键字的类,也就是被测类AccionPSD2,而非被实例化的ApiPSD2Jazztel。

修复方案

二选一即可:

方案一:切换到JUnit4(改动量最小)

将测试类中所有JUnit5的注解替换为JUnit4对应实现,不需要修改核心测试逻辑:

  • 删除org.junit.jupiter.api.*下的相关导入,替换为:
    • org.junit.Before 替换原@BeforeEach
    • org.junit.Test 替换原@Test
    • org.junit.Assert 替换原Assertions
      修改后的测试类基础结构参考:
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest(AccionPSD2.class)
public class AccionPSD2Test {
    private AccionPSD2 instance;
    private final String mockString = "testString";

    @Before
    public void init() {
        instance = new AccionPSD2();
    }

    @Test
    public void testEnviarSolicitudPSD2() throws Exception {
        // 原有测试逻辑保持不变即可
        ApiPSD2Jazztel mockApiPSD2Jazztel = PowerMockito.mock(ApiPSD2Jazztel.class);
        PowerMockito.whenNew(ApiPSD2Jazztel.class).withAnyArguments().thenReturn(mockApiPSD2Jazztel);
        // 后续mock配置、参数构造、反射调用、断言逻辑不需要调整
    }
}

方案二:保留JUnit5,更换PowerMock扩展

PowerMock原生不支持JUnit5,需要引入专门的JUnit5扩展依赖:

  1. 引入和现有PowerMock版本一致的powermock-module-junit5依赖
  2. 将@RunWith(PowerMockRunner.class)替换为@ExtendWith(PowerMockExtension.class)
  3. 保留原有JUnit5注解和@PrepareForTest(AccionPSD2.class)配置
    基础结构参考:
import org.junit.jupiter.api.extension.ExtendWith;
import org.powermock.modules.junit5.PowerMockExtension;

@ExtendWith(PowerMockExtension.class)
@PrepareForTest(AccionPSD2.class)
public class AccionPSD2Test {
    // 原有JUnit5代码逻辑不需要调整
}
额外排查点

如果调整版本后仍存在拦截失效问题,逐一检查:

  • 确认ApiPSD2Jazztel类、其构造方法不是final修饰,PowerMock无法拦截final类的实例化逻辑
  • 确认PowerMock与Mockito版本匹配:例如PowerMock 2.0.x最高兼容Mockito 3.5.x,版本错位会导致插桩失效
  • 确认whenNew的配置在调用被测方法之前执行,你的现有代码顺序符合要求,不需要调整

内容的提问来源于stack exchange,提问作者Catalin Mares

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 13:15:47