应优先将继承改为组合,即子类通过构造注入依赖而非 extends 父类,使测试时可轻松 mock 依赖;若无法重构,则确保父类正确初始化、覆盖 protected 方法暴露测试接口,慎用 powermock。

避免直接测试继承链中的子类
比如 DataSource extends ExtendedDataSource 这类结构,若直接 new DataSource() 并调用 getConnection(),很可能触发父类中 getUser() 等未设置的依赖,抛出 IllegalStateException。试图用 @Mock 注解 mock 抽象父类或子类自身,既违反测试原则,又常因 final/static/private 方法导致 Mockito 失效。
优先把继承改为组合(Composition over Inheritance)
这是最根本、最可持续的解法。让子类不再“是”父类,而是“有”一个父类能力的组件:
- 定义
ExtendedDataSource为接口(推荐)或非 final 抽象类 - 重构
DataSource:去掉extends,改用构造函数注入依赖 - 所有对父类逻辑的调用,改为委托给该依赖对象
这样,测试时就能完全控制这个依赖——用 Mockito 轻松 mock 它的行为,无需碰真实继承链。
用 Mockito 编写可信赖的测试
组合重构后,测试变得清晰直接:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
mock(ExtendedDataSource.class)创建模拟对象 - 用
when(...).thenReturn(...)预设方法返回值(如 getConnection 返回 mock Connection) - 构造被测对象:
new DataSource(mockExtendedDS) - 调用公共方法(如
setup(props)),断言结果是否匹配预期
整个过程不依赖任何真实初始化逻辑,也不需要 PowerMock 或字节码增强,稳定、快速、可读性强。
实在无法重构时的临时方案
如果遗留系统暂时不能改设计,且必须测试带继承的类:
- 确保父类有无参构造器,或显式调用
super(...)初始化关键字段 - 对 protected 方法,可通过子类覆盖方式“暴露”为 public(仅用于测试,加
@TestOnly注释) - 慎用 PowerMock mock 构造器或静态方法——它会让测试变慢、难维护,且干扰覆盖率统计
这类做法只是权宜之计,长期仍应推动向组合+接口的设计演进。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










