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

如何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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 21:37:34