如何用Mockito测试调用工具方法的Service层方法?报错求助
问题分析与解决方案
你遇到的InvalidUseOfMatchersException异常主要有两个原因:
@InjectMocks创建的EntityService是真实对象,Mockito的when()只能用于@Mock或@Spy标记的对象,直接对真实对象使用when()会触发异常。thenReturn(Mockito.any(DTO.class))是错误用法:any()这类参数匹配器只能用在方法的参数位置,thenReturn()需要传入具体的返回值实例,不能用匹配器替代。
下面给出两种可行的解决方案:
方案一:测试完整业务逻辑(推荐)
convertEntityToDTO是Service内部的转换逻辑,属于getAllDTOs功能的一部分,直接测试完整流程更符合单元测试的初衷。
修正后的测试代码
@Mock private EntityRepository entityRepo; @InjectMocks private EntityService entityService; @Test public void EntityService_GetAll_ReturnsDTOList() { // 1. 准备模拟的实体数据 Entity mockEntity = new Entity(); mockEntity.setId(1L); mockEntity.setName("测试实体"); List<Entity> mockEntityList = List.of(mockEntity); // 2. Mock仓库层返回模拟数据 when(entityRepo.findAll()).thenReturn(mockEntityList); // 3. 调用待测试方法 List<DTO> dtoList = entityService.getAllDTOs(); // 4. 验证结果 Assertions.assertThat(dtoList).isNotNull(); Assertions.assertThat(dtoList.size()).isEqualTo(1); // 可进一步验证DTO字段与实体的映射正确性 Assertions.assertThat(dtoList.get(0).getId()).isEqualTo(mockEntity.getId()); }
方案二:隔离转换逻辑(适合复杂依赖场景)
如果ModelMapper是复杂依赖,想单独隔离转换逻辑,可以将ModelMapper改为依赖注入,而非在方法内直接实例化,这样就能Mock转换过程。
第一步:修改Service代码
// 将ModelMapper作为依赖注入 private final ModelMapper modelMapper; private final EntityRepository entityRepo; // 构造函数注入依赖 public EntityService(EntityRepository entityRepo, ModelMapper modelMapper) { this.entityRepo = entityRepo; this.modelMapper = modelMapper; // 初始化配置移到构造函数 modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE); } public List<DTO> getAllDTOs(){ return entityRepo.findAll() .stream() .map(this::convertEntityToDTO) .collect(Collectors.toList()); } public DTO convertEntityToDTO(Entity entity) { return modelMapper.map(entity, DTO.class); }
第二步:编写测试代码
@Mock private EntityRepository entityRepo; @Mock private ModelMapper modelMapper; @InjectMocks private EntityService entityService; @Test public void EntityService_GetAll_ReturnsDTOList() { // 准备模拟数据 Entity mockEntity = new Entity(); DTO mockDto = new DTO(); List<Entity> mockEntityList = List.of(mockEntity); // Mock仓库层返回数据 when(entityRepo.findAll()).thenReturn(mockEntityList); // Mock转换逻辑 when(modelMapper.map(mockEntity, DTO.class)).thenReturn(mockDto); // 调用待测试方法 List<DTO> dtoList = entityService.getAllDTOs(); // 验证结果 Assertions.assertThat(dtoList).isNotNull(); Assertions.assertThat(dtoList).contains(mockDto); }
内容的提问来源于stack exchange,提问作者Marko Strukovina
相关产品推荐
相关产品推荐

