抽象类不可直接实例化,需通过具体子类(如匿名内部类)实现抽象方法后测试其已实现逻辑;可提取通用功能至工具类单独测试;mockito可模拟抽象类但仅适用于协作行为验证。

抽象类本身不能直接实例化,所以不能像普通类那样用 new 创建对象来测。但你可以通过创建一个**具体子类**(哪怕只是测试用的临时类)来实例化它,再对抽象类中已实现的方法、受保护的字段、模板方法逻辑等进行测试。
用匿名内部类或局部子类实例化抽象类
这是最常用也最轻量的方式——不污染生产代码,只在测试里临时继承抽象类并实现其抽象方法。
- 如果抽象类只有少量抽象方法,可用匿名类快速补全
- 确保只实现“必须实现”的抽象方法,其他保持默认行为即可
- 重点测试抽象类中 已提供实现的方法(比如模板方法、工具方法、钩子方法)
public abstract class DataProcessor {
public final String process(String input) {
if (input == null) return "NULL";
return doActualProcess(input.trim());
}
protected abstract String doActualProcess(String s);
}
测试写法:
@Test
void testProcess_handlesNull() {
DataProcessor processor = new DataProcessor() {
@Override
protected String doActualProcess(String s) {
return s.toUpperCase();
}
};
assertEquals("NULL", processor.process(null));
}
@Test
void testProcess_trimsAndUppercases() {
DataProcessor processor = new DataProcessor() {
@Override
protected String doActualProcess(String s) {
return s;
}
};
assertEquals("HELLO", processor.process(" hello "));
}
提取可测试的公共逻辑到独立工具类
如果抽象类里有大量与继承无关的通用逻辑(比如校验、格式化、计算),建议将其拆到 普通工具类 中,然后在抽象类里调用。这样工具类可直接单元测试,无需绕过抽象限制。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 降低抽象类复杂度,提升可测性
- 避免为测一行校验逻辑而写一堆测试子类
- 符合单一职责原则,也方便复用
用 Mockito 模拟抽象类(需谨慎)
Mockito 从 3.4.0 起支持 mock(AbstractClass.class),但仅适用于不需要调用真实方法的场景(比如只验证方法是否被调用)。若要测试真实逻辑,仍需子类方式。
- 适合测试抽象类中依赖注入的协作行为(如调用 service 方法)
- 不能用于验证
final方法或私有逻辑的实际输出 - 注意:mock 后所有非 stub 的方法返回默认值(null/0/false),不是真实行为
@Test
void testTemplateMethod_callsHook() {
DataProcessor mock = mock(DataProcessor.class);
// 必须 stub 抽象方法,否则抛异常
when(mock.doActualProcess("x")).thenReturn("X");
String result = mock.process(" x ");
assertEquals("X", result);
verify(mock).doActualProcess("x");
}
测试抽象类的构造逻辑和字段初始化
抽象类的构造函数会被子类调用,因此字段赋值、参数校验等逻辑也可测。
- 在测试子类中调用
super(...),观察是否抛出预期异常 - 检查 protected 字段是否按预期初始化(可通过子类访问或反射)
- 避免过度依赖反射;优先用子类 getter 或暴露测试用的 protected 方法
不复杂但容易忽略:抽象类不是“不可测”,而是需要换一种实例化思路。核心是聚焦它真正提供的能力——已实现的行为、约束契约、模板流程,而不是执着于“它不能 new”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










