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

如何测试调用父类受保护方法的DataSource类?解决用户未设置异常

问题解决方案

异常核心原因是测试实例化的DataSource对象,其继承链中AbstractSource的user属性未初始化,调用getUser()时触发了未设置的检查逻辑(虽代码未体现,但异常提示明确指向此问题)。不需要Mock所有相关类,以下是几种可行解决思路:

方案1:直接设置user属性(最简单场景)

如果AbstractSource提供了setUser()方法,或user是protected属性,直接在测试中给实例赋值:

@Test
public void datatest() {
    DataSource dataSource = new DataSource();
    // 若有setUser方法直接调用
    dataSource.setUser("test-user");
    // 若属性为protected,可临时用反射赋值(不推荐长期使用)
    // Field userField = AbstractSource.class.getDeclaredField("user");
    // userField.setAccessible(true);
    // userField.set(dataSource, "test-user");
    
    dataSource.getConnection(props);
}

方案2:用Mockito Partial Mock Stub getUser()方法

如果user的初始化逻辑复杂、无法直接访问,可使用Mockito的部分Mock功能,仅替换getUser()的返回值,保留其他方法的真实逻辑:

@RunWith(MockitoJUnitRunner.class)
public class DataSourceTest {

    @Mock
    Properties props;

    @Test
    public void datatest() {
        // 创建部分Mock的DataSource实例,仅mock getUser方法
        DataSource dataSource = Mockito.spy(new DataSource());
        // 指定getUser返回测试用的user值
        Mockito.when(dataSource.getUser()).thenReturn("test-user");
        
        dataSource.getConnection(props);
    }
}

注意:使用spy()而非mock(),目的是保留getConnection()、setup()的原有业务逻辑,仅隔离getUser()的依赖。

方案3:重构业务代码,依赖注入user(长期最优解)

当前继承链中user的初始化逻辑耦合性过高,可重构AbstractSource,通过构造方法或依赖注入传入user:

public abstract class AbstractSource extends AnotherAbstractClass{
    private final String user;

    // 构造方法注入user,同时增加参数校验
    protected AbstractSource(String user) {
        if (user == null || user.isEmpty()) {
            throw new IllegalStateException("user not set");
        }
        this.user = user;
    }

    public String getUser() {
        return user;
    }
}

// 子类同步修改构造方法
class ExtendedDataSource extends AbstractSource {
    public ExtendedDataSource(String user) {
        super(user);
    }
    // 原有业务逻辑不变
}

class DataSource extends ExtendedDataSource {
    public DataSource(String user) {
        super(user);
    }
    // 原有业务逻辑不变
}

测试时直接传入测试用user,无需任何Mock:

@Test
public void datatest() {
    DataSource dataSource = new DataSource("test-user");
    dataSource.getConnection(props);
}

这种方式让代码依赖关系更清晰,测试维护成本更低,是长期迭代的最优选择。

关于Mock抽象类的疑问

不需要Mock整个抽象类,除非你需要完全隔离AbstractSource的所有逻辑。你的测试目标是验证DataSource、ExtendedDataSource的setup()、getConnection()逻辑,只需处理getUser()这一个依赖点即可,无需Mock所有相关类。

内容的提问来源于stack exchange,提问作者Jeet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:46:30