You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mockito测试调用工具方法的Service层方法?报错求助

问题分析与解决方案

你遇到的InvalidUseOfMatchersException异常主要有两个原因:

  1. @InjectMocks创建的EntityService是真实对象,Mockito的when()只能用于@Mock或@Spy标记的对象,直接对真实对象使用when()会触发异常。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 06:41:33