2016个人网站备案,豪华网站设计,简述网站内容如何优化,网站关键字可以修改吗Mockito 使用注解进行单元测试详解
Mockito 提供了一系列注解来简化测试代码的编写#xff0c;减少手动创建和管理 Mock 对象的样板代码。结合 JUnit 5#xff0c;可以更高效地构建清晰、易维护的单元测试。 1. 核心注解概览
注解作用Mock创建并注入一个 Mock 对象#xf…
Mockito 使用注解进行单元测试详解
Mockito 提供了一系列注解来简化测试代码的编写减少手动创建和管理 Mock 对象的样板代码。结合 JUnit 5可以更高效地构建清晰、易维护的单元测试。 1. 核心注解概览
注解作用Mock创建并注入一个 Mock 对象完全模拟方法默认返回空或默认值。Spy创建并注入一个 Spy 对象部分模拟默认调用真实方法除非显式覆盖。InjectMocks自动将 Mock 或 Spy 对象注入到被测类中依赖注入。Captor自动初始化 ArgumentCaptor用于捕获方法参数。ExtendWith启用 Mockito 扩展JUnit 5 必需替代旧版 RunWith。 2. 注解配置与启用
2.1 启用 Mockito 支持
在测试类上添加 ExtendWith(MockitoExtension.class)激活 Mockito 注解功能
ExtendWith(MockitoExtension.class) // JUnit 5 必加
public class UserServiceTest {// 测试代码...
}2.2 自动初始化注解
无需手动调用 MockitoAnnotations.openMocks(this)ExtendWith 已自动处理。 3. 注解使用详解
3.1 Mock 注解
作用创建完全模拟的依赖对象。
示例场景
public class UserService {private final UserDao userDao;public UserService(UserDao userDao) {this.userDao userDao;}public User getUserById(int id) {return userDao.findById(id);}
}测试代码
ExtendWith(MockitoExtension.class)
class UserServiceTest {Mockprivate UserDao mockUserDao; // 自动创建 Mock 对象InjectMocksprivate UserService userService; // 自动注入 mockUserDaoTestvoid getUserById_ShouldReturnUser() {// 配置 Mock 行为when(mockUserDao.findById(1)).thenReturn(new User(1, Alice));// 调用被测方法User user userService.getUserById(1);// 验证结果assertEquals(Alice, user.getName());verify(mockUserDao).findById(1);}
}3.2 Spy 注解
作用创建部分模拟对象保留真实方法逻辑除非显式覆盖。
示例场景
public class PaymentService {public boolean validateCard(String cardNumber) {return cardNumber ! null cardNumber.length() 16;}public boolean processPayment(String cardNumber) {if (!validateCard(cardNumber)) return false;// 真实支付逻辑...return true;}
}测试代码
ExtendWith(MockitoExtension.class)
class PaymentServiceTest {Spy // 部分模拟保留真实方法private PaymentService spyPaymentService;Testvoid processPayment_ShouldUseMockedValidation() {// 覆盖 validateCard 方法doReturn(true).when(spyPaymentService).validateCard(anyString());// 调用被测方法processPayment 会调用被覆盖的 validateCardboolean result spyPaymentService.processPayment(invalid_card);assertTrue(result);verify(spyPaymentService).validateCard(invalid_card);}
}3.3 InjectMocks 注解
作用自动将 Mock 或 Spy 对象注入到被测类中。
注入规则
构造器注入优先匹配参数类型和数量。Setter 注入调用 setter 方法。字段注入最后直接反射注入字段。
示例
ExtendWith(MockitoExtension.class)
class OrderServiceTest {Mockprivate InventoryService inventoryService;Mockprivate PaymentService paymentService;InjectMocks // 自动注入 inventoryService 和 paymentServiceprivate OrderService orderService;Testvoid placeOrder_ShouldCheckInventory() {when(inventoryService.checkStock(anyString())).thenReturn(true);orderService.placeOrder(product_123);verify(inventoryService).checkStock(product_123);}
}3.4 Captor 注解
作用自动创建参数捕获器简化参数验证。
示例
ExtendWith(MockitoExtension.class)
class NotificationServiceTest {Mockprivate EmailClient mockEmailClient;InjectMocksprivate NotificationService notificationService;Captor // 自动初始化 ArgumentCaptorprivate ArgumentCaptorEmailRequest emailCaptor;Testvoid sendWelcomeEmail_ShouldCaptureEmailContent() {notificationService.sendWelcomeEmail(userexample.com);verify(mockEmailClient).send(emailCaptor.capture());EmailRequest captured emailCaptor.getValue();assertEquals(userexample.com, captured.getTo());assertTrue(captured.getSubject().contains(Welcome));}
}4. 常见问题与解决方案
问题解决方案Mock 对象为 null检查是否添加 ExtendWith(MockitoExtension.class)。依赖注入失败确保 InjectMocks 类的依赖项有对应的 Mock 或 Spy 对象。Spy 对象调用真实方法导致异常使用 doReturn().when() 替代 when().thenReturn() 避免执行真实方法。参数捕获器未初始化使用 Captor 替代手动创建 ArgumentCaptor。 5. 高级整合与 Spring Boot 测试结合
在 Spring Boot 测试中可使用 MockBean 替换容器中的 Bean
SpringBootTest
public class ProductServiceIntegrationTest {MockBean // Spring 管理的 Mockprivate InventoryService mockInventoryService;Autowiredprivate ProductService productService;Testvoid reserveProduct_ShouldUseMockInventory() {when(mockInventoryService.reserve(anyString())).thenReturn(true);boolean result productService.reserveProduct(product_123);assertTrue(result);}
}6. 最佳实践
保持测试简洁使用注解减少手动初始化代码。明确依赖关系通过 InjectMocks 明确被测类的依赖注入方式。避免过度 Mock仅 Mock 外部依赖保留核心逻辑的真实性。结合 AssertJ使用流式断言提高测试可读性assertThat(capturedEmail.getSubject()).contains(Welcome);通过合理使用 Mockito 注解可以显著提升单元测试的编写效率和可维护性。