使用PowerMockito Mock同类方法B时仍执行内部逻辑并报NPE的解决办法
解决同一类内部方法Mock失效的问题
你遇到的问题是因为直接对真实对象存根内部方法时,Mockito/PowerMockito会先执行真实方法逻辑再生成存根,所以方法B的代码还是会跑,导致NPE。要Mock同一类的内部方法,需要用「部分Mock(Spy)」的方式,配合正确的语法。
正确的实现步骤:
- 用PowerMockito创建类A的Spy实例:Spy允许你保留对象的真实行为,同时Mock指定方法。
- 使用
doReturn().when()语法:这种语法不会先执行真实方法,直接存根返回值,避免触发方法B的内部逻辑。 - 添加必要的PowerMock注解:确保测试类能被PowerMock处理,支持Mock类内部的protected方法。
完整测试代码示例:
import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(ClassA.class) // 必须准备要Mock的类 public class ClassATest { @Test public void testMethodA() { // 创建ClassA的Spy实例 ClassA classA = PowerMockito.spy(new ClassA()); // 存根方法B,直接返回true,不执行真实逻辑 PowerMockito.doReturn(true).when(classA).B("任意参数", "任意参数"); // 如果需要匹配任意参数,也可以用匹配器: // PowerMockito.doReturn(true).when(classA).B(Mockito.anyString(), Mockito.anyString()); // 调用方法A,此时内部的B方法会被Mock,不会执行真实逻辑 classA.A(1, "test", 1.0); // 后续的断言逻辑... } }
关键说明:
- 不要用
when(classA.B(...)).thenReturn(true),这种写法会先调用真实的B方法,这就是你之前遇到NPE的原因。 @PrepareForTest注解必须包含要Mock的类(这里是ClassA),因为PowerMock需要修改类的字节码来支持Spy和内部方法Mock。- 如果方法B是private的,写法类似,只是存根时需要用
PowerMockito.doReturn(true).when(classA, "B", 参数...)的形式。
内容的提问来源于stack exchange,提问作者Buntom
相关产品推荐
相关产品推荐

