如何Stub第三方抽象基类中的protected方法以测试子类?
问题描述
我在使用一个第三方库,它包含一个抽象基类AbstractBaseClass,我的应用代码需要继承这个类。子类在处理流程中会调用基类的protected方法。现在我想隔离测试自己的子类,需要Stub这个基类的protected方法。
我尝试创建子类实例的Mockito spy,并Stub基类的public方法,这种方式是有效的,但对protected方法行不通——直接写如下代码会编译报错:
MySubclass obj = Mockito.spy(new MySubclass()); Mockito.when(obj.protectedMethod()).thenReturn(42); // 错误:protectedMethod()在AbstractBaseClass中是protected访问权限
请问有没有其他方法可以为这个protected方法指定Stub?
解决方案
以下是几种可行的Stub方案,可根据项目情况选择:
1. 创建匿名子类重写protected方法
直接在测试代码中创建MySubclass的匿名子类,重写目标protected方法并返回预设的Stub值,再包装成spy:
MySubclass obj = Mockito.spy(new MySubclass() { @Override protected int protectedMethod() { return 42; // 返回需要的Stub结果 } });
这种方式无需额外依赖,代码简洁,适合简单的Stub场景。
2. 编写测试专属子类暴露protected方法
在测试代码中定义一个继承自MySubclass的子类,将基类的protected方法重写为public,之后就能直接用Mockito常规方式Stub:
// 测试类中定义的专属子类 public class TestableMySubclass extends MySubclass { @Override public int protectedMethod() { // 将访问权限改为public return super.protectedMethod(); } }
测试时使用该子类的spy:
TestableMySubclass obj = Mockito.spy(new TestableMySubclass()); Mockito.when(obj.protectedMethod()).thenReturn(42);
3. 使用PowerMockito通过方法名Stub(需引入依赖)
如果项目允许引入PowerMockito依赖,可直接通过方法名字符串Stub protected方法,绕过编译期的访问权限检查:
MySubclass obj = PowerMockito.spy(new MySubclass()); PowerMockito.when(obj, "protectedMethod").thenReturn(42);
4. 结合反射与Mockito的doReturn
若不想引入额外依赖,可通过反射获取protected方法,配合Mockito的doReturn完成Stub:
MySubclass obj = Mockito.spy(new MySubclass()); try { Method protectedMethod = AbstractBaseClass.class.getDeclaredMethod("protectedMethod"); protectedMethod.setAccessible(true); // 用doReturn避免触发真实方法逻辑 Mockito.doReturn(42).when(obj).protectedMethod(); } catch (NoSuchMethodException e) { // 处理方法不存在的异常 e.printStackTrace(); }
注:若测试类与AbstractBaseClass不在同一包,直接调用obj.protectedMethod()仍会编译报错,此时可通过反射调用该方法触发Stub逻辑。
内容的提问来源于stack exchange,提问作者Magnus Reftel
相关产品推荐
相关产品推荐

