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

升级依赖库后代码覆盖率下降,Jacoco排除规则失效求助

问题概述

升级项目依赖至Gradle 7.2、Spring Boot 2.7.13、JUnit 4.13后,未做功能变更或新增类,但代码覆盖率从84%降至49%。排查Jacoco报告发现,使用@RunWith(MockitoJUnitRunner.class)的测试类覆盖率为0,尝试@InjectMocks注解、排除对应类、添加@Tag("ignoreaccept")标记均未解决问题。

涉及代码与配置

测试类(com/**/accept包下)

@RunWith(MockitoJUnitRunner.class)
public class AbstractProcTest {

    private LSD ls = new LSD();

    private AbstractProc processor = new SmallProc(ls);

    @Mock
    private RestClient restClient;

}

build.gradle测试配置

test {
    useJUnitPlatform {
        excludeTags "ignoreaccept"
    }
    finalizedBy jacocoTestReport 
}

Jacoco配置

jacocoTestCoverageVerification {
    violationRules {
        rule {
            element = 'BUNDLE'
            excludes = ['**/com/vk/isr/kvr/accept/**/*']
            limit {
                minimum = 0.84
            }
        }
    }
}

jacocoTestReport {
    group 'documentation'
    reports {
        xml.enabled true
        csv.enabled false
        html.destination file("${buildDir}/result/report")
    }
}

jacocoTestCoverageVerification.mustRunAfter jacocoTestReport

check.dependsOn jacocoTestReport
check.dependsOn jacocoTestCoverageVerification
compileJava.dependsOn(processResources)
问题原因分析
  1. JUnit平台兼容性问题:Gradle 7+的useJUnitPlatform默认仅支持JUnit 5测试,JUnit 4的@RunWith测试若未配置JUnit Vintage引擎,会导致测试未被执行,对应生产类的代码覆盖率无法被统计,同时未执行的测试不会标记生产类为已覆盖,拉低整体覆盖率。
  2. 排除规则未生效:
    • 测试类的@Tag标记可能未被正确识别,或排除路径有误,导致测试仍被执行但无有效覆盖;
    • Jacoco的excludes规则仅排除指定路径的生产类覆盖率统计,若当前排除的是测试类路径而非对应生产类,无法解决未覆盖问题。
  3. Mockito注解使用不当:测试类中@Mock的restClient未注入到processor,且无实际@Test方法,测试未执行任何业务逻辑,导致覆盖率为0。
解决方案

方案1:让JUnit4测试正常执行(保留测试并统计覆盖率)

步骤1:添加JUnit Vintage引擎依赖

在build.gradle中添加依赖,让JUnit平台支持JUnit4测试:

dependencies {
    // 其他依赖...
    testImplementation 'org.junit.vintage:junit-vintage-engine:5.9.2'
    testImplementation 'org.mockito:mockito-junit-jupiter:4.11.0'
}

步骤2:修正Mockito注解与添加测试方法

确保依赖注入生效,并添加实际测试逻辑:

@RunWith(MockitoJUnitRunner.class)
public class AbstractProcTest {

    private LSD ls = new LSD();

    @InjectMocks
    private AbstractProc processor = new SmallProc(ls);

    @Mock
    private RestClient restClient;

    // 添加实际测试方法
    @Test
    public void testProcessorExecute() {
        // 模拟RestClient行为
        when(restClient.callApi(anyString())).thenReturn("mockResult");
        // 执行处理器逻辑
        processor.execute();
        // 验证交互
        verify(restClient, times(1)).callApi(anyString());
    }
}

方案2:完全忽略相关测试与对应生产类(跳过测试且不统计覆盖率)

步骤1:正确跳过测试类

修改test任务配置,直接排除测试包,确保测试不被执行:

test {
    useJUnitPlatform {
        excludeTags "ignoreaccept"
        // 直接排除accept包下的所有测试类
        exclude '**/accept/**'
    }
    finalizedBy jacocoTestReport 
}

步骤2:修正Jacoco排除规则

将测试对应的生产类加入排除列表,确保这些类的覆盖率不被纳入统计:

jacocoTestCoverageVerification {
    violationRules {
        rule {
            element = 'BUNDLE'
            excludes = [
                '**/com/vk/isr/kvr/accept/**/*',
                // 添加对应的生产类路径,示例如下
                '**/com/vk/isr/kvr/xxx/AbstractProc*',
                '**/com/vk/isr/kvr/xxx/SmallProc*',
                '**/com/vk/isr/kvr/xxx/LSD*'
            ]
            limit {
                minimum = 0.84
            }
        }
    }
}

方案3:迁移至JUnit5(长期最优解)

将JUnit4测试迁移为JUnit5格式,适配Gradle 7+的JUnit平台:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class AbstractProcTest {

    private LSD ls = new LSD();

    @InjectMocks
    private AbstractProc processor = new SmallProc(ls);

    @Mock
    private RestClient restClient;

    @Test
    public void testProcessorExecute() {
        // 测试逻辑同前
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:34:50