使用 PowerMock 测试带有静态方法 Java 的最终类时没有代码覆盖

问题描述

我正在为一个 final 类编写一个测试用例,其中定义了 static 方法。 现在测试用例运行良好,但当我点击代码覆盖率时,它显示 0% ,尽管测试用例运行良好。

我使用 PowerMockEasyMock 并使用 Junit4

我的班

public class Meals {
    public static String getName(String name) {
        if (name == null) {
            return "bad";
        } else {
            return "good";
        }
    }
}

还有我的测试用例

import static org.junit.Assert.assertEquals;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.powermockrunner;

@RunWith(powermockrunner.class)
@PrepareForTest(Meals.class)
public class MealsTest {

    @Before
    public void setUp() throws Exception {
        PowerMock.mockStatic(Meals.class);
    }

    @Test
    public void testMeals() {

        EasyMock.expect(Meals.getName(null)).andReturn("bad");
        PowerMock.replayAll();
        assertEquals("bad",Meals.getName(null));
        PowerMock.verifyAll();

    }

}

据我所知是因为注释 PreparefortestRunWith ,但我不确定。

所以任何帮助将不胜感激。

解决方法

众所周知,PowerMock 会杀死代码覆盖率。我认为这是因为他们在一个特殊的类加载器中加载自定义类,并且代码覆盖工具没有检测这些代码,因为它是在事实之后。除了不使用 PowerMock 之外,我认为这些都不是解决方案。

我们是否同意您的测试目前没有测试任何内容?只是测试 PowerMock 是否正常工作。

,

如果您使用 jacoco + Gradle,您可以通过以下方式启用离线检测

task instrument(dependsOn: [classes,project.configurations.jacocoAnt]) {
    inputs.files classes.outputs.files
    File outputDir = new File(project.buildDir,'instrumentedClasses')
    outputs.dir outputDir
    doFirst {
        project.delete(outputDir)
        ant.taskdef(
                resource: 'org/jacoco/ant/antlib.xml',classpath: project.configurations.jacocoAnt.asPath,uri: 'jacoco'
        )
        def instrumented = false
        if (file(sourceSets.main.java.outputDir).exists()) {
            def instrumentedClassedDir = "${outputDir}/${sourceSets.main.java}"
            print sourceSets.main.java.outputDir
            ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {

                fileset(dir: sourceSets.main.java.outputDir,includes: '**/*.class')
            }
            //Replace the classes dir in the test classpath with the instrumented one
            sourceSets.test.runtimeClasspath -= files(sourceSets.main.java.outputDir)
            sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
            instrumented = true
        }
        if (instrumented) {
            test.jvmArgs += '-noverify'
        }
    }
}
test {
    dependsOn instrument
    useJUnit()
    finalizedBy jacocoTestReport // report is always generated after tests run
}

代码归功于 https://github.com/esdk/g30l0/commit/82af4c9aad50aadc40d940471fe1b934473170c7

这是一个悬而未决的问题 https://github.com/gradle/gradle/issues/2429