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

Mockito测试含返回值方法时内部void方法报错的解决咨询

解决Mockito报错:CannotStubVoidMethodWithReturnValue,测试包含void方法调用的带返回值方法

我看出来你在测试SimRepo.getData()方法时踩了Mockito的常见坑,先帮你拆解问题,再给你正确的测试写法。

先分析你测试代码的问题

你现在的测试代码犯了两个关键错误:

  1. 直接实例化了真实的SimRepo对象,却试图用Mockito stub它的方法:Mockito只能用来mock/stub被Mockito创建的对象(比如用@Mock或Mockito.mock()生成的对象),真实对象的方法无法被stub,这相当于你根本没在测试getData()的真实逻辑,而是在测试一个mock的空实现。
  2. 没有mockSimRepo的依赖roomDao:当你调用真实SimRepo的getData()时,会执行真实的roomDao.updateData()方法,而如果roomDao是真实的数据库DAO,这会直接操作数据库,而且Mockito会因为真实方法的执行触发校验,抛出"无法给void方法设置返回值"的错误。

正确的测试步骤和代码

首先,确保SimRepo的依赖(roomDao、converterData)是通过构造函数传入的(依赖注入),这样测试时可以轻松替换为mock对象。

下面是修正后的测试代码:

@ExtendWith(MockitoExtension.class)
public class SimRepoTest {
    // Mock SimRepo的依赖:RoomDao和ConverterData
    @Mock
    private RoomDao roomDao;
    @Mock
    private ConverterData converterData;

    // 待测试的SimRepo实例,注入mock依赖
    private SimRepo simRepo;

    @BeforeEach
    void setUp() {
        // 初始化SimRepo,传入mock的依赖
        simRepo = new SimRepo(roomDao, converterData);
    }

    @Test
    public void getData_ShouldConvertData_UpdateAndReturnResult() {
        // 1. 准备测试数据
        SimBasket<DataEntity, SimRequest> testRequest = new SimBasket<>();
        Entity expectedOutData = new Entity();

        // 2. Mock converterData的convertNetToDatabase方法,指定返回值
        Mockito.when(converterData.convertNetToDatabase(testRequest)).thenReturn(expectedOutData);

        // 3. 调用待测试方法
        IEntity actualResult = simRepo.getData(testRequest);

        // 4. 验证结果
        // 检查返回值是否符合预期
        assertEquals(expectedOutData, actualResult);
        // 验证roomDao的updateData方法是否被正确调用(参数正确,调用一次)
        Mockito.verify(roomDao, Mockito.times(1)).updateData(expectedOutData);
    }
}

关键要点说明

  • 处理void方法:对于roomDao.updateData()这种void方法,你不需要给它指定返回值(这就是报错的根源),mock对象默认会对void方法执行doNothing(),也就是什么都不做。如果你需要模拟抛出异常的场景,可以用:
    doThrow(new RuntimeException("测试异常")).when(roomDao).updateData(any(Entity.class));
    
  • 测试核心逻辑:我们测试的是getData()的逻辑:是否正确调用了converterData.convertNetToDatabase(),是否把转换后的结果传给了roomDao.updateData(),以及是否正确返回了转换后的对象。
  • 隔离依赖:通过mock所有外部依赖,我们可以确保测试只关注SimRepo自身的代码,不会受到数据库或其他组件的影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 21:42:29