将 jacoco 脱机检测与 Powermock 配合使用时缺少 jacoco.exec 文件



尽管这篇文章显然展示了使用 powermock 和 jacoco 的解决方案,但我无法让它在一个非常简单的项目中工作(可在 GitHub 上找到)。

就我而言,测试正确执行,但 jacoco.exec 文件丢失,因此 jacoco 不检查覆盖范围。

测试类:

@RunWith(PowerMockRunner.class)
@PrepareOnlyThisForTest(Util.class)
@PowerMockIgnore("org.jacoco.agent.rt.*")
public class UtilTest {
    @Test
    public void testSay() throws Exception {
        PowerMockito.mockStatic(Util.class);
        Mockito.when(Util.say(Mockito.anyString())).thenReturn("hello:mandy");
        Assert.assertEquals("hello:mandy", Util.say("sid"));
    }
}

实用.java

public class Util {
    private Util() {}
    public static String say(String s) {
        return "hello:"+s;
    }
}

绒球.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.codependent.jacocopower</groupId>
    <artifactId>jacoco-powermock</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.18.1</version>
                <configuration>
                    <systemPropertyVariables>
                        <jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
                    </systemPropertyVariables>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.version}</version>
                <executions>
                    <execution>
                        <id>default-instrument</id>
                        <goals>
                            <goal>instrument</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-restore-instrumented-classes</id>
                        <goals>
                            <goal>restore-instrumented-classes</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-report</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <rule>
                                    <element>CLASS</element>
                                    <limits>
                                        <limit>
                                            <counter>LINE</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.50</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
     <dependencies>
        <dependency>
            <groupId>org.jacoco</groupId>
            <artifactId>org.jacoco.agent</artifactId>
            <classifier>runtime</classifier>
            <version>${jacoco.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <properties>
        <powermock.version>1.5.4</powermock.version>
        <jacoco.version>0.7.4.201502262128</jacoco.version>
    </properties>
</project>

Maven 执行跟踪,抱怨找不到 jacoco.exec 文件:

>> mvn clean verify
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building jacoco-powermock 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ jacoco-powermock ---
[INFO] Deleting C:SoftDesarrollo6-WorkspaceslibertyGeconjacoco-powermocktarget
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ jacoco-powermock ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ jacoco-powermock ---
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 1 source file to C:SoftDesarrollo6-WorkspaceslibertyGeconjacoco-powermocktargetclasses
[INFO]
[INFO] --- jacoco-maven-plugin:0.7.4.201502262128:instrument (default-instrument) @ jacoco-powermock ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ jacoco-powermock ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ jacoco-powermock ---
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 1 source file to C:SoftDesarrollo6-WorkspaceslibertyGeconjacoco-powermocktargettest-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ jacoco-powermock ---
[INFO] Surefire report directory: C:SoftDesarrollo6-WorkspaceslibertyGeconjacoco-powermocktargetsurefire-reports
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.codependent.jacoco.UtilTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.239 sec - in com.codependent.jacoco.UtilTest
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- jacoco-maven-plugin:0.7.4.201502262128:restore-instrumented-classes (default-restore-instrumented-classes) @ jacoco-powermock ---
[INFO]
[INFO] --- jacoco-maven-plugin:0.7.4.201502262128:report (default-report) @ jacoco-powermock ---
[INFO] Skipping JaCoCo execution due to missing execution data file:C:SoftDesarrollo6-WorkspaceslibertyGeconjacoco-powermocktargetjacoco.exec
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ jacoco-powermock ---
[INFO] Building jar: C:SoftDesarrollo6-WorkspaceslibertyGeconjacoco-powermocktargetjacoco-powermock-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- jacoco-maven-plugin:0.7.4.201502262128:check (default-check) @ jacoco-powermock ---
[INFO] Skipping JaCoCo execution due to missing execution data file:C:SoftDesarrollo6-WorkspaceslibertyGeconjacoco-powermocktargetjacoco.exec
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.987s
[INFO] Finished at: Thu Jan 21 09:13:55 CET 2016
[INFO] Final Memory: 23M/331M
[INFO] ------------------------------------------------------------------------

更新:(在GitHub上)

根据 Lencalot 提供的答案,将生成 jacoco.exec 文件,但以下情况一直说 ServiceImpl 类覆盖率为 0%:

服务进出口

public class ServiceImpl implements Service{
    public String operation() {
        return Util.say("Hi!");
    }
}

服务测试

@RunWith(PowerMockRunner.class)
@PrepareForTest({Util.class})
public class ServiceTest {
    private Service service = new ServiceImpl();
    @Test
    public void testOperation() throws Exception {
        PowerMockito.mockStatic(Util.class);
        Mockito.when(Util.say(Mockito.anyString())).thenReturn("Bye!");
        Assert.assertEquals("Bye!", service.operation());
    }
}

跟踪:

[WARNING] Rule violated for class com.codependent.jacoco.ServiceImpl: lines covered ratio is 0.00, but expected minimum is 0.50
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>${jacoco.version}</version>
    <configuration>
        <append>true</append>
    </configuration>
    <executions>
        <execution>
            <id>default-instrument</id>
            <goals>
                <goal>instrument</goal>
            </goals>
            <configuration>
                <includes>
                    <include>**/*test*</include>
                </includes>
            </configuration>
        </execution>
        <execution>
            <id>default-restore-instrumented-classes</id>
            <goals>
                <goal>restore-instrumented-classes</goal>
            </goals>
            <configuration>
                <includes>
                    <include>**/*test*</include>
                </includes>
            </configuration>
        </execution>
        <execution>
            <id>Prepare-Jacoco</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <excludes>
                    <exclude>**/*test*</exclude>
                </excludes>
            </configuration>
        </execution>
    </executions>
</plugin>

您现在可以删除检查,我们可以先尝试让它工作。

将 Jacoco 依赖项更新为如下所示

<dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.agent</artifactId>
    <version>${jacoco.version}</version>
    <scope>test</scope>
</dependency> 

让你的万无一失的插件看起来像这样:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>${argLine}</argLine>
    </configuration>
</plugin>

在您的属性部分中,将其添加为,并更改您的 jacoco 版本:

<jacoco.version>0.7.5.201505241946</jacoco.version>
<jacoco.outputDir>${project.basedir}/target/jacoco.exec</jacoco.outputDir>

@codependent 这里有一个你想嘲笑的例子。

让我们假设你的 Util.class 有更多的代码,很多实例化,甚至可能触及一些服务器端的东西,甚至可能它是一个 UI。您不想实例化 User.class只是为了在名为 UtilUser 的其他类中测试单个方法.class

protected class UtilUser {
    protected UtilUser() {}
    public Boolean checkSay(String s) {
        String expectedString = "hello:" + s;
        String actualString = Util.say(s);
        if (expectedString.equals(actualString){
           return true;
        } else { 
           return false;
        }
    }
}

要对 UtilUser 进行单元测试,您需要命中所有分支。因此,在您的测试中,您将模拟 Util.class,并在一个单元测试中强制它返回正确的字符串,而在另一个测试中,它返回不正确的字符串。您不关心测试User.class,您知道它会相应地运行,或者您将有另一个测试来处理它。对于单元测试 UtilUser,您可以期望 Util 返回正确的字符串或不正确的字符串,并且您希望测试这两种可能性。

模拟有时间和地点,它们是一个很好的工具,但不要认为它们应该经常使用。请参考以下文章,它将为您提供有关何时应该使用模拟的良好见解:何时模拟

相关内容

  • 没有找到相关文章

最新更新