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

如何Mock会修改入参的DAO方法?解决测试分支无法覆盖问题

问题场景

单元测试中需Mock DAO层的createRecord方法,该方法实际逻辑为:创建数据库记录后,给传入的RecordDto类型入参设置主键ID,同时返回受影响行数。

当前测试仅通过when(dao.createRecord(any(RecordDto.class))).thenReturn(1);模拟了返回值,未模拟入参ID的修改操作,导致被测方法createSomething中input.getId() != null的分支代码无法被覆盖。

当前测试代码

RecordDto input = new RecordDto();
input.setId(null);
input.setName("test");

when(dao.createRecord(any(RecordDto.class))).thenReturn(1);

createSomething(input);

待Mock的DAO方法

public int createRecord(RecordDto input) {
   int updatedRowCount = 0;
   int primaryKey = /* 数据库调用生成主键 */;
   updatedRowCount += primaryKey != null ? 1 : 0;
   input.setId(primaryKey); // 核心逻辑:修改入参的ID
   return updatedRowCount;
}

被测类方法

public void createSomething(RecordDto input) {
   int rowsUpdated = dao.createRecord(input);
   if (input.getId() != null) {
      // 该分支无法被当前测试覆盖
      doSomething();
   }
}

解决方案

要同时模拟返回值和入参修改,可借助Mockito的Answer接口自定义Mock方法的执行逻辑,有两种常用写法:

写法1:使用thenAnswer(推荐用于有返回值的方法)

RecordDto input = new RecordDto();
input.setId(null);
input.setName("test");

// 自定义Mock行为:修改入参ID并返回指定行数
when(dao.createRecord(any(RecordDto.class)))
    .thenAnswer(invocation -> {
        // 获取方法调用时传入的RecordDto参数
        RecordDto dto = invocation.getArgument(0);
        // 模拟数据库生成的主键ID,根据实际类型调整值(如Long/Integer)
        dto.setId(123L);
        // 返回受影响行数
        return 1;
    });

createSomething(input);
// 此时input.getId()会被设置为123L,分支代码可被正常覆盖

写法2:使用doAnswer(适合void方法或特殊匹配场景)

如果需要绕过Mockito的默认匹配逻辑,或者Mock的是void方法,可改用doAnswer:

RecordDto input = new RecordDto();
input.setId(null);
input.setName("test");

doAnswer(invocation -> {
    RecordDto dto = invocation.getArgument(0);
    dto.setId(123L);
    return 1; // 返回受影响行数,非void方法需指定返回值
}).when(dao).createRecord(any(RecordDto.class));

createSomething(input);

原理说明

通过Answer接口,你可以拦截Mock方法的调用,获取传入的参数对象,修改其属性后再返回指定结果,完全复刻真实DAO方法的行为,从而覆盖被测方法中的所有分支。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:53:31