测试UserServiceImpl的abc()方法时如何mock间接依赖的UserRepository?
测试方案解答
首先根据你的测试目标,可以分为两种场景选择对应方案:
场景1:仅做UserServiceImpl的纯单元测试(推荐)
这种场景下不需要Mock UserRepository,单测的核心是只验证当前层的逻辑,你只需要Mock UserServiceImpl的直接依赖UserDao即可,完全隔离下层实现:
@ExtendWith(MockitoExtension.class) public class UserServiceImplTest { @Mock private UserDao userDao; @InjectMocks private UserServiceImpl userService; @Test void testAbc() { // 直接Mock UserDao.xyz的行为,无需关心其内部依赖 doNothing().when(userDao).xyz("a"); userService.abc(); // 验证UserDao的调用符合预期即可 verify(userDao, times(1)).xyz("a"); } }
该方案执行速度快、完全隔离外部依赖,符合分层测试的设计原则。
场景2:需要连带验证UserDao逻辑,必须Mock UserRepository
如果你的测试用例需要同时验证abc()调用后UserDao内部的执行逻辑,可以选择以下两种实现方式:
方式A:纯Mockito自动注入依赖
通过Mockito的注解自动完成Mock对象的层级注入:
@ExtendWith(MockitoExtension.class) public class UserServiceImplTest { @Mock private UserRepository userRepository; // Mock的UserRepository会自动注入到UserDao中 @InjectMocks private UserDao userDao; // 构造好的UserDao会自动注入到UserServiceImpl中 @InjectMocks private UserServiceImpl userService; @Test void testAbc() { // 提前Mock UserRepository的返回值 User mockUser = new User(); when(userRepository.findByName("mike")).thenReturn(Optional.of(mockUser)); userService.abc(); // 可按需验证UserRepository的调用是否符合预期 verify(userRepository, times(1)).findByName("mike"); } }
方式B:Spring集成测试环境下替换Bean
如果是在Spring Boot集成测试场景,直接用@MockBean替换Spring容器中的真实UserRepository即可:
@SpringBootTest public class UserServiceImplTest { @MockBean private UserRepository userRepository; @Autowired private UserServiceImpl userService; @Test void testAbc() { when(userRepository.findByName("mike")).thenReturn(Optional.empty()); userService.abc(); verify(userRepository).findByName("mike"); } }
注意:如果没有特殊的跨层验证需求,优先选择场景1的纯单元测试方案,维护成本更低
内容的提问来源于stack exchange,提问作者Nisal Pubudu
相关产品推荐
相关产品推荐

