如何测试调用父类受保护方法的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
相关产品推荐
相关产品推荐

