unit-test-service-layer 是做什么的?
提供使用 Mockito 进行服务层单元测试的模式。创建隔离的测试,模拟仓库调用,验证方法调用,测试异常场景,并存根外部 API 响应。用于测试服务行为和业务逻辑,无需数据库或外部服务。
概述
此技能专注于服务层的单元测试,使您能够在不启动数据库或外部依赖的情况下,验证业务逻辑的正确性。通过 Mockito 模拟依赖项,您可以隔离地测试服务类,确保测试快速、可靠且易于维护。
核心模式
- 模拟(Mock)依赖项:使用
@Mock或Mockito.mock()创建服务依赖的模拟实例。 - 注入模拟对象:使用
@InjectMocks自动将模拟对象注入到被测服务中。 - 定义模拟行为:使用
when().thenReturn()指定模拟方法的返回值。 - 执行测试:调用被测服务的方法。
- 验证交互:使用
verify()检查方法是否被调用及调用次数。 - 异常场景:使用
when().thenThrow()测试异常处理逻辑。
示例代码
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void shouldReturnUserWhenFound() {
// Given
User expected = new User(1L, "Alice");
when(userRepository.findById(1L)).thenReturn(Optional.of(expected));
// When
User actual = userService.getUserById(1L);
// Then
assertEquals(expected, actual);
verify(userRepository).findById(1L);
}
@Test
void shouldThrowExceptionWhenUserNotFound() {
// Given
when(userRepository.findById(99L)).thenReturn(Optional.empty());
// When & Then
assertThrows(UserNotFoundException.class, () -> userService.getUserById(99L));
verify(userRepository).findById(99L);
}
}
最佳实践
- 保持测试隔离:每个测试应仅测试一个逻辑单元。
- 使用有意义的测试名称:遵循
should[预期行为]_when[条件]模式。 - 避免过度模拟:仅模拟直接依赖,不要模拟值对象。
- 验证交互:确保关键方法被正确调用。
- 测试边界条件:包括空值、异常和极值输入。
支持平台
- Java 8+
- JUnit 5
- Mockito 3.x+
- Spring Boot(可选,通过
@MockBean集成)