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

Mockito单元测试中Sonar未检测到方法覆盖率问题排查

问题:Mock getName方法后Sonar覆盖率仍为0%

我尝试对返回String类型的getName方法进行Mock以获取Sonar覆盖率,目标方法代码如下:

public String getName(String prmTableName) {
        GetParameterRequest parameterRequest = new GetParameterRequest();
        String absParamStorePath = env.getProperty("amazon.aws.parameter") + prmTableName + "/"
                + env.getProperty("amazon.aws.env");
        parameterRequest.withName("/someurl");
        parameterRequest.withName(absParamStorePath).setWithDecryption(Boolean.valueOf(true));
        GetParameterResult parameterResult = awsSimpleSystemsManagement.getParameter(parameterRequest);
        System.out.println("Parameterstore Table Response:  " + parameterResult.getParameter().getValue());
        return parameterResult.getParameter().getValue();
    }

我的JUnit测试实现如下:

@Mock
DAO dao;

@BeforeEach
public void setup(){
    MockitoAnnotations.initMocks(this);
    mockmvc= MockMvcBuilders.standaloneSetup(dao).build();
}

@Test
public void testName(){
    String value="";
    when(dao.getName("storeName"))
            .then(t->value);
}

但运行Sonar后该方法覆盖率为0%,怀疑测试未实际执行目标方法,请问问题出在哪里?


问题根源与解决方案

  • Mock对象使用错误,未执行真实方法
    你用@Mock创建的是DAO的模拟对象,这个对象的getName是Mockito生成的空实现,你写的when(...)只是定义模拟方法的返回值,但从未调用过真实类的getName方法,自然不会产生任何代码覆盖率。

  • 测试逻辑完全颠倒
    要覆盖真实类的getName方法,正确的做法是:

    1. 创建真实类的实例(而非Mock对象)
    2. 对真实类依赖的外部组件(如env、awsSimpleSystemsManagement)进行Mock,避免调用真实AWS接口
    3. 调用真实类实例的getName方法,验证结果是否符合预期

修正后的测试示例(假设真实类名为ParameterService):

@InjectMocks
private ParameterService parameterService; // 真实类实例,依赖由Mockito自动注入

@Mock
private Environment env; // 依赖的Environment对象Mock
@Mock
private AWSSimpleSystemsManagement awsSimpleSystemsManagement; // 依赖的AWS客户端Mock

@BeforeEach
public void setup(){
    MockitoAnnotations.initMocks(this);
}

@Test
public void testGetName() {
    // 1. Mock配置属性的返回值
    when(env.getProperty("amazon.aws.parameter")).thenReturn("/test/base/path/");
    when(env.getProperty("amazon.aws.env")).thenReturn("dev");
    
    // 2. Mock AWS接口的返回结果
    GetParameterResult mockResult = new GetParameterResult();
    Parameter mockParam = new Parameter();
    mockParam.setValue("expected-table-name");
    mockResult.setParameter(mockParam);
    when(awsSimpleSystemsManagement.getParameter(any(GetParameterRequest.class)))
            .thenReturn(mockResult);
    
    // 3. 调用真实类的目标方法(这一步才会执行getName的真实代码,产生覆盖率)
    String result = parameterService.getName("storeName");
    
    // 4. 验证返回结果和依赖调用(可选但推荐)
    assertEquals("expected-table-name", result);
    verify(awsSimpleSystemsManagement, times(1)).getParameter(any(GetParameterRequest.class));
}
  • 额外提示:原目标方法存在冗余代码
    原方法中parameterRequest.withName("/someurl");这行代码无效,因为下一行parameterRequest.withName(absParamStorePath)会覆盖参数名称,建议清理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 23:27:07