如何正确替换Powermock注解 迁移测试至JUnit5+Mockito?
核心前提:使用Mockito 3.4.0+版本(推荐4.x+稳定版),其原生支持静态方法、final类/方法、构造函数的Mock能力,无需依赖Powermock的字节码增强和自定义类加载器,可完全覆盖三个注解的常用场景,逐个替换规则如下:
替换
@PowerMockRunnerDelegate(SpringRunner.class)
JUnit 5抛弃了JUnit4的Runner机制,采用扩展模型实现测试能力增强,支持同时注册多个扩展。直接在测试类上添加如下注解即可同时启用Spring测试上下文和Mockito注解支持:@ExtendWith({SpringExtension.class, MockitoExtension.class})如果测试类已经加了
@SpringBootTest注解,该注解默认内置了SpringExtension,无需重复声明,只保留MockitoExtension即可。替换
@PrepareForTest({A.class, B.class})
该注解在Powermock中用于标记需要做字节码增强、用来Mock静态方法、final方法、构造函数、私有方法的目标类,Mockito不需要类级别注解做预标记,根据要Mock的场景直接在测试逻辑中用对应API即可:- 若需Mock A、B的静态方法:使用
mockStatic()方法,配合try-with-resources语法块限定Mock生命周期,避免污染其他测试用例:@Test void testSomething() { try (MockedStatic<A> mockA = mockStatic(A.class); MockedStatic<B> mockB = mockStatic(B.class)) { // 定义Mock行为,例如 mockA.when(A::getStaticVal).thenReturn("test"); // 执行测试逻辑、做断言 } // 代码块执行结束后自动卸载A、B的Mock,静态方法恢复原生逻辑 } - 若需Mock A、B的构造函数:使用
mockConstruction()方法,写法和mockStatic()一致,在try块内即可拦截对应类的new实例化操作。 - 若仅需Mock A、B的final实例方法:直接用
@Mock注解声明对应类的Mock实例即可,Mockito 2.x+版本默认支持final类、final方法的Mock,无需额外配置。
- 若需Mock A、B的静态方法:使用
替换
@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.*", "com.sun.org.apache.xalan.*", "javax.activation.*", "javax.management.*"})
该注解在Powermock中用于排除指定包下的类,避免Powermock自定义类加载器加载这些类时触发类转换、类冲突问题。Mockito的Mock增强基于Java Instrumentation机制实现,不会替换应用的类加载器,不存在Powermock的类加载冲突问题,该注解无任何等效配置,直接删除即可,不需要额外写忽略规则。
注意:如果使用3.x版本的Mockito,需要将测试依赖中的
mockito-core替换为mockito-inline才能启用静态方法、构造函数Mock能力;Mockito 4.0+版本已将该能力合入核心包,默认开启,无需额外依赖调整。
内容的提问来源于stack exchange,提问作者Nabla

