一、为什么需要 Mock 框架?
在单元测试中,Mock 框架用于创建虚拟对象替代实际依赖组件,确保测试聚焦于被测单元本身,隔离外部影响。对于 Spring Boot 项目来说,Mock 通常用于替代 Service、Repository、HTTP 客户端等组件,提升测试速度和稳定性。
二、主流 Java Mock 框架介绍
框架 | 特点 | 适用场景 |
---|---|---|
Mockito | 使用最广泛,语法简洁,集成简单,支持行为验证和交互验证 | 大多数业务逻辑的单元测试 |
EasyMock | 基于接口生成 Mock,使用录制-回放机制,语法风格不同于 Mockito | 传统项目或接口驱动系统 |
PowerMock | 可 Mock 静态方法、final 类、构造函数等 | 旧代码改造、遗留系统测试、难以解耦的代码单元 |
三、核心原理与架构理解
Mockito 原理简述
Mockito 基于 Java 动态代理(JDK Proxy / CGLIB)实现,通过运行时动态生成代理对象来拦截方法调用。
@Mock
:创建模拟对象@InjectMocks
:自动注入依赖Mockito.when().thenReturn()
:定义行为Mockito.verify()
:验证方法调用
EasyMock 原理简述
EasyMock 使用“录制-回放”机制,测试先设置行为预期,然后执行方法,最后进行验证。
expect(service.getName()).andReturn("mock").once()
replay(service)
verify(service)
PowerMock 原理简述
PowerMock 基于 ASM 字节码操作实现,可以绕过 JVM 限制 mock:
- 静态方法(static)
- final 类、final 方法
- 构造函数
- private 方法
但这带来了字节码污染问题,不推荐与 JUnit5 一起使用(需使用 PowerMockRunner 或 MockitoJUnitRunner)
四、实践 DEMO:一个真实业务场景对比
场景背景:测试订单创建服务
public class OrderService {
private PaymentService paymentService;
public boolean createOrder(Order order) {
boolean paid = paymentService.pay(order.getId(