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

Mockito报错:findById()无法返回Boolean,需返回Optional的问题排查

问题分析与解决

错误根源

你遇到的报错核心原因是:试图用Mockito存根真实对象的方法。你的actorService是通过@InjectMocks创建的真实业务类实例,而非Mock对象。当你执行when(actorService.actorExists(actorId)).thenReturn(true)时,Mockito会触发真实的actorExists方法执行,内部检测到方法调用链中存在返回值类型不匹配的冲突(错误提示里的findById()应该返回Optional却被错误关联到Boolean类型的返回逻辑)。

另外,这行存根代码本身完全多余:你已经mock了creativesRepository.findById(actorId)返回Optional.of(actor),真实的actorService.actorExists方法会基于这个mock结果自然返回true,根本不需要额外存根。

解决方案

方案一:移除多余的存根代码(推荐)

直接删除when(actorService.actorExists(actorId)).thenReturn(true)这行代码即可。修改后的测试类如下:

@RunWith(MockitoJUnitRunner.class)
public class MovieServiceTest {
    @Mock
    private MovieRepository movieRepository;
    @Mock
    ActorRepository creativesRepository;
    @InjectMocks
    private MovieService movieService;
    @InjectMocks
    private ActorService actorService;

    // 注意:@RunWith(MockitoJUnitRunner.class)已完成mock初始化,无需再调用openMocks
    // 可删除@BeforeEach方法,或保留时去掉openMocks调用

    @Test
    public void testDeleteActorNotInMovie() throws CreativesDeletionException, CreativesNotFoundException {
        Long actorId = 1L;
        Actor actor = new Actor();
        actor.setId(actorId);
        when(creativesRepository.findById(actorId)).thenReturn(Optional.of(actor));
        
        // 此时调用actorService.actorExists(actorId)会自然返回true,可直接用于后续测试逻辑
    }
}

方案二:将actorService改为Spy对象(仅需存根真实对象方法时使用)

如果确实需要跳过actorService的真实逻辑、直接存根方法返回值,可以将actorService声明为Spy对象,Mockito允许对Spy对象的部分方法进行存根:

@RunWith(MockitoJUnitRunner.class)
public class MovieServiceTest {
    @Mock
    private MovieRepository movieRepository;
    @Mock
    ActorRepository creativesRepository;
    @InjectMocks
    private MovieService movieService;
    @Spy // 添加@Spy注解
    @InjectMocks
    private ActorService actorService;

    @Test
    public void testDeleteActorNotInMovie() throws CreativesDeletionException, CreativesNotFoundException {
        Long actorId = 1L;
        when(actorService.actorExists(actorId)).thenReturn(true);
        
        // 后续测试逻辑
    }
}

额外优化点

测试类中@RunWith(MockitoJUnitRunner.class)和MockitoAnnotations.openMocks(this)功能重复,二者选其一即可:

  • 保留@RunWith(MockitoJUnitRunner.class)的话,删除@BeforeEach中的MockitoAnnotations.openMocks(this);
  • 若使用JUnit 5,推荐替换为@ExtendWith(MockitoExtension.class),无需@RunWith和openMocks调用。

内容的提问来源于stack exchange,提问作者WowBow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:55:41