在Powermock中使用jacoco脱机检测时缺少jacoco.exec文件 [英] Missing jacoco.exec file when using jacoco offline instrumentation with Powermock

查看:163
本文介绍了在Powermock中使用jacoco脱机检测时缺少jacoco.exec文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽管此 post 显示了使用powermock和jacoco的解决方案,但我无法使其在一个非常简单的项目中工作(在GitHub上提供).

Despite apparently this post showed a solution to using powermock and jacoco, I haven't been able to make it work in a pretty simple project (available on GitHub).

就我而言,测试可以正确执行,但是缺少jacoco.exec文件,因此jacoco不会检查覆盖率.

In my case, the test executes correctly but the jacoco.exec file is missing so jacoco doesn't check coverage.

测试类别:

@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"));
    }

}

Util.java

public class Util {

    private Util() {}

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

}

pom.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文件:

Maven execution trace, complaining that no jacoco.exec file was found:

>> 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:\SoftDesarrollo\6-Workspaces\libertyGecon\jacoco-powermock\target
[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:\SoftDesarrollo\6-Workspaces\libertyGecon\jacoco-powermock\target\classes
[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:\SoftDesarrollo\6-Workspaces\libertyGecon\jacoco-powermock\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ jacoco-powermock ---
[INFO] Surefire report directory: C:\SoftDesarrollo\6-Workspaces\libertyGecon\jacoco-powermock\target\surefire-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:\SoftDesarrollo\6-Workspaces\libertyGecon\jacoco-powermock\target\jacoco.exec
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ jacoco-powermock ---
[INFO] Building jar: C:\SoftDesarrollo\6-Workspaces\libertyGecon\jacoco-powermock\target\jacoco-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:\SoftDesarrollo\6-Workspaces\libertyGecon\jacoco-powermock\target\jacoco.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上)

UPDATE: (here on GitHub)

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

With the answer provided by Lencalot the jacoco.exec file is generated but the following scenario keeps saying that the ServiceImpl class coverage is 0%:

ServiceImpl

public class ServiceImpl implements Service{

    public String operation() {
        return Util.say("Hi!");
    }

}

ServiceTest

@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>

您可以删除立即检查",我们可以尝试首先使其消失.

you can remove Check for now, we can try to get it working with out that first.

将您的Jacoco依赖项更新为这样

Update your Jacoco dependency to look like this

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

使您的maven surefire插件看起来像这样:

Make you maven surefire plugin look like this:

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

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

in your properties section Add this as, and change your jacoco Version:

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

@codependent这里是您为什么要嘲笑的示例.

@codependent Heres an example of why you want to mock.

让我们假设您的Util.class具有更多的代码,大量的实例化,甚至可能涉及到服务器端的东西,甚至还有UI.您不想实例化User.class只是为了测试其他名为UtilUser.class

Lets assume your Util.class has a lot more code, a lot of instantiations and maybe it even touches some server side stuff, hell maybe even its a UI. You don't want to instantiate User.class just to test a single method in some other class called 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返回正确的字符串或不正确的字符串,并且您想测试这两种可能性.

To unit test UtilUser, you want to hit all branches. So in your test you would mock the Util.class, and in one unit test force it to return the correct string, and in another test have it return an incorrect string. You don't care about testing User.class, you know it will behave accordingly or you will have another test to take care of that. For unit testing UtilUser, you can expect Util to either return a correct string or an incorrect string, and you want to test both possibilities.

有很多时间和地点可以进行模拟,并且它们是了解的绝佳工具,但不要以为应该经常使用它们.请参考以下文章,它将使您深入了解何时应使用模拟:何时模拟

Theres a time and a place for mocks and they are a great tool to know, but DO NOT think they should be used often. Please refer to the following article, it will give you good insight into when you should use mocks: When To Mock

这篇关于在Powermock中使用jacoco脱机检测时缺少jacoco.exec文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆