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

Mockito测试Spring Boot服务无代码覆盖率问题及正确写法求解

问题原因

你的测试用例没有覆盖到代码,核心是测试代码本身存在大量语法/用法错误,根本没有正常执行到被测服务的真实逻辑,具体问题如下:

  • 基础语法笔误导致代码无法正常编译/运行:
    • 测试方法返回值错写为voi,正确应为void
    • 数值类名拼写错误:Bigecimal 正确为BigDecimal
    • 响应对象变量名前后不一致:定义时命名为rsp,后续赋值、传参时错写为不存在的vetResp
    • 空catch块吞掉了所有运行时异常,就算代码抛错你也看不到任何报错信息,自然不知道逻辑根本没走通
  • Mockito用法错误:
    • 打桩语法写错:doReturn(result).when(myRepository.update(data))是非法写法,doReturn().when()的语法要求when()内只传入mock对象本身,对应的方法调用要写在when()代码块之后
    • 注解使用逻辑错误:@Spy注解修饰的对象不会自动注入@Mock标记的依赖,默认调用无参构造生成的实例中myRepo字段为null,调用时直接触发空指针,又被你的空catch吞掉,根本执行不到后续业务逻辑。你替换成@InjectMocks后仍无覆盖,本质是前面的语法、打桩错误没有解决,不是注解本身的问题
  • 额外注意:你贴出的业务代码本身也存在笔误,比如myRepo.update(ata)中的ata是未定义变量,应为方法内构造的data;@Autowire、Logger初始化类名、异常日志文本也存在拼写错误,这些问题也会导致代码无法正常运行,需要先修正。
可直接运行的覆盖测试示例

首先先修正MyService中的明显笔误,确保业务代码可正常编译:

@Service
@Transactional
public class MyService {
    private static final Logger log = LoggerFactory.getLogger(MyService.class);
    @Autowired
    private MyRepository myRepo;

    public Map<String, Object> myMethod(Response rsp, Request req) {
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("PROCESS_I", req.getProcessI());
        data.put("REQUEST_I", req.getRequestI());
        data.put("TYPE_COE", req.getTypeCoe());
        data.put("STATUS_COE", rsp.getStatusCoe());
        
        Map<String, Object> result = null;
        try {
            result = myRepo.update(data);
        } catch (Exception e) {
            log.error("Error occurred during update : " + e.getMessage());
        }   

        return result;
    }
}

对应的测试类覆盖正常执行、异常抛出两个场景,即可覆盖该方法全部代码行:

@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
    
    @Mock
    private MyRepository myRepository;
    
    // 用@InjectMocks自动把mock的myRepository注入到真实MyService实例中
    @InjectMocks
    private MyService myService;

    @Test
    public void testMyMethod_Success() {
        // 构造请求、响应测试参数
        Request req = new Request();
        req.setProcessI(new BigDecimal("43850"));
        req.setRequestI(new BigDecimal("146717"));
        req.setTypeCoe("ABC");
        
        Response rsp = new Response();
        rsp.setStatusCoe("N");

        // 构造mock返回值
        Map<String, Object> mockResult = new HashMap<>();
        mockResult.put("updateCount", 1);
        // 正确打桩:任意Map参数传入update时返回预设结果
        when(myRepository.update(any(Map.class))).thenReturn(mockResult);

        // 调用被测方法
        Map<String, Object> result = myService.myMethod(rsp, req);
        
        // 断言返回结果符合预期
        assertEquals(1, result.get("updateCount"));
        // 验证repository方法被正确调用
        verify(myRepository, times(1)).update(any(Map.class));

        // 如需校验传入update的参数是否组装正确,可用ArgumentCaptor捕获后断言
        ArgumentCaptor<Map> paramCaptor = ArgumentCaptor.forClass(Map.class);
        verify(myRepository).update(paramCaptor.capture());
        Map passedParam = paramCaptor.getValue();
        assertEquals(new BigDecimal("43850"), passedParam.get("PROCESS_I"));
        assertEquals("N", passedParam.get("STATUS_COE"));
    }

    @Test
    public void testMyMethod_WhenRepoThrowException() {
        // 构造请求、响应测试参数
        Request req = new Request();
        req.setProcessI(new BigDecimal("43850"));
        req.setRequestI(new BigDecimal("146717"));
        req.setTypeCoe("ABC");
        
        Response rsp = new Response();
        rsp.setStatusCoe("N");

        // 打桩:调用update时抛出异常,覆盖catch分支逻辑
        when(myRepository.update(any(Map.class))).thenThrow(new RuntimeException("db connection error"));

        // 调用被测方法
        Map<String, Object> result = myService.myMethod(rsp, req);
        
        // 断言异常场景返回null
        assertNull(result);
        verify(myRepository, times(1)).update(any(Map.class));
    }
}
注意点
  • 测试代码里不要写空catch块吞异常,否则出错了完全没有排查线索
  • 测普通服务方法不需要用@Spy,@InjectMocks会创建真实的服务实例,同时把所有@Mock的依赖注入进去,调用方法时会走真实的业务逻辑,完全满足单元测试隔离外部依赖的需求
  • 打桩时如果不需要精确匹配参数,用any()系列的参数匹配器即可;如果要校验方法内部参数组装是否正确,用ArgumentCaptor捕获参数后断言即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:39:21