多态为Mock提供基础:需面向接口编程、依赖抽象,避免final类和静态依赖;Mock可控制行为分支验证逻辑;TestableMock等工具可补足边界但不替代接口设计。

多态本身不直接“配合”Mock框架,而是为Mock提供了天然基础——只要代码面向接口编程、依赖抽象而非实现,Mock才能顺利注入并替换行为。
依赖接口是前提
Mock生效的前提是:被测类不直接 new 具体实现,而是通过构造函数、Setter 或 DI 容器接收接口类型依赖。例如:
- 订单服务持有 PaymentGateway 接口,而非 AlipayGateway 实例
- 测试时可传入 MockPaymentGateway,完全绕过真实支付调用
- 若实现类被 final 修饰,Mockito 等主流框架无法生成子类代理,Mock将失败
测试中主动控制行为分支
多态让同一接口调用在不同实现下产生不同结果,这正是单元测试验证逻辑覆盖的关键:
- 注入 Mock 实现,主动抛出 PaymentFailureException,验证降级逻辑是否触发
- 让 Mock 返回 success = false,检查订单状态更新是否正确回滚
- 模拟网络延迟(如 sleep 2s),检验超时配置与线程池响应是否合理
避免破坏多态可测性的设计陷阱
有些编码习惯会悄悄切断多态与测试的连接:
立即学习“Java免费学习笔记(深入)”;
- 接口方法声明具体异常(如 throws AlipayApiException),迫使调用方感知实现细节;应统一转为自定义业务异常(PaymentFailureException)
- 实现类内部强依赖静态工具类或单例状态,导致切换实现时行为不可控、测试结果不稳定
- 把核心逻辑写在 private 方法里却未封装成可测接口,Mock 无法切入,只能靠集成测试覆盖
TestableMock 等轻量框架的适配要点
像 TestableMock 这类支持 Mock 私有/静态方法的工具,并不削弱多态价值,反而补足其边界:
- 仍建议优先面向接口设计,保证主干逻辑清晰、可替换
- 对遗留系统中难以改造的紧耦合代码,可用 TestableMock 直接 Mock 工具类方法,但需注意:Mock 容器类必须与被测类同包,且 @MockInvoke 必须指定 targetClass
- 日志、加解密、时间获取等通用能力,尽量抽成接口,比反复 Mock 静态方法更可持续


















