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方法,正确的做法是:- 创建真实类的实例(而非Mock对象)
- 对真实类依赖的外部组件(如
env、awsSimpleSystemsManagement)进行Mock,避免调用真实AWS接口 - 调用真实类实例的
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
相关产品推荐
相关产品推荐

