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

JUnit测试运行通过但Jacoco显示0%覆盖,如何处理Mapper内新建对象的测试问题

问题1:如何Mock方法内部new出来的对象并完成Setter注入

你当前代码里的StudentOldTestingReturn、OldBatchName都是在业务方法内部直接实例化的,默认Mockito无法直接Mock这类对象,两种解决方案:

方案1:使用Mockito 3.5+提供的mockConstruction特性(无需改造业务代码)

在测试方法里可以临时Mock指定类的所有构造方法调用,示例代码:

@Test
void OldLogicTestingMockTest() throws Exception {
    // 先Mock OldBatchName的构造
    try (MockedConstruction<OldBatchName> mockedBatch = Mockito.mockConstruction(OldBatchName.class,
            (mock, context) -> {
                // 模拟setter赋值后的返回值
                Mockito.when(mock.getId()).thenReturn("mockId");
                Mockito.when(mock.getName()).thenReturn("mockName");
            })) {
        // 再Mock StudentOldTestingReturn的构造
        try (MockedConstruction<StudentOldTestingReturn> mockedReturn = Mockito.mockConstruction(StudentOldTestingReturn.class)) {
            // 执行业务逻辑
            NewUseInsideMethods insideMethods = new NewUseInsideMethods();
            StudentOldTesting param = new StudentOldTesting();
            param.setName("testName");
            StudentOldTestingReturn result = insideMethods.OldLogicTesting(param);

            // 验证构造方法确实被调用了
            Assertions.assertEquals(1, mockedBatch.constructed().size());
            Assertions.assertEquals(1, mockedReturn.constructed().size());
            // 验证setter确实被调用
            StudentOldTestingReturn returnMock = mockedReturn.constructed().get(0);
            Mockito.verify(returnMock).setId("mockId");
            Mockito.verify(returnMock).setName("testName");
        }
    }
}

方案2:改造业务代码提升可测试性(更推荐的长期方案)

把方法内部需要实例化的类作为依赖注入,或者提供工厂类来创建对象,避免在业务方法里硬编码new对象:

// 改造后的业务类
public class NewUseInsideMethods {
    // 把需要创建的对象通过Setter注入进来,或者用构造注入
    private Supplier<StudentOldTestingReturn> returnSupplier = StudentOldTestingReturn::new;
    private Supplier<OldBatchName> batchNameSupplier = OldBatchName::new;

    public void setReturnSupplier(Supplier<StudentOldTestingReturn> returnSupplier) {
        this.returnSupplier = returnSupplier;
    }

    public void setBatchNameSupplier(Supplier<OldBatchName> batchNameSupplier) {
        this.batchNameSupplier = batchNameSupplier;
    }

    public StudentOldTestingReturn OldLogicTesting(StudentOldTesting Student) {
        StudentOldTestingReturn sturentReturn = returnSupplier.get();
        OldBatchName batchName = batchNameSupplier.get();
        batchName.setId("1");
        batchName.setName("test");
        sturentReturn.setId(batchName.getId());
        sturentReturn.setName(Student.getName());
        return sturentReturn;
    }
}

改造后测试的时候直接把Mock对象的Supplier注入即可,不需要用特殊的Mock构造能力,兼容性更好。


问题2:Eclipse测试跑通但Jacoco覆盖率为0的常见解决方法

  • 检查Jacoco插件配置:如果是Maven项目,确认jacoco-maven-plugin已经绑定到test和report生命周期,配置示例:
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.11</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>
  • 检查测试类和源码类的包路径是否一致:测试类要和被测类放在同一个包名下(src/test/java和src/main/java的包结构要完全对应),否则Jacoco可能识别不到对应关系
  • 检查是否有配置排除了被测类:查看pom里的Jacoco配置有没有<excludes>标签把你的Mapper类排除了
  • 不要用PowerMock:PowerMock会修改字节码和Jacoco的插桩冲突,如果必须用PowerMock要配置 offline instrumentation
  • 执行测试前先clean:每次生成覆盖率报告前先执行mvn clean test,避免旧的class文件影响统计结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 11:24:04