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替换原@BeforeEachorg.junit.Test替换原@Testorg.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扩展依赖:
- 引入和现有PowerMock版本一致的
powermock-module-junit5依赖 - 将
@RunWith(PowerMockRunner.class)替换为@ExtendWith(PowerMockExtension.class) - 保留原有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
相关产品推荐
相关产品推荐

