Mockito测试含返回值方法时内部void方法报错的解决咨询
解决Mockito报错:CannotStubVoidMethodWithReturnValue,测试包含void方法调用的带返回值方法
我看出来你在测试SimRepo.getData()方法时踩了Mockito的常见坑,先帮你拆解问题,再给你正确的测试写法。
先分析你测试代码的问题
你现在的测试代码犯了两个关键错误:
- 直接实例化了真实的
SimRepo对象,却试图用Mockito stub它的方法:Mockito只能用来mock/stub被Mockito创建的对象(比如用@Mock或Mockito.mock()生成的对象),真实对象的方法无法被stub,这相当于你根本没在测试getData()的真实逻辑,而是在测试一个mock的空实现。 - 没有mock
SimRepo的依赖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
相关产品推荐
相关产品推荐

