2016-01-21 74 views
2

儘管顯然這post顯示了使用powermock和jacoco的解決方案,但我還是無法使它在一個非常簡單的項目(available on GitHub)中工作。使用jacoco脫機儀器與Powermock時缺少jacoco.exec文件

在我的情況下,測試正確執行,但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")); 
    } 

} 

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文件發現:

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

更新:(here on GitHub

隨着由Lencalot提供的答案生成jacoco.exec文件,但下面場景口口聲聲說ServiceImpl類覆蓋率爲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 

回答

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

讓你Maven的萬無一失插件看起來像這樣:

<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 Heres一個你爲什麼要模擬的例子。讓我們假設你的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返回一個正確的字符串或一個不正確的字符串,並且你想測試兩種可能性。

這是一個時間和地點的嘲笑,他們是一個偉大的工具知道,但不要認爲他們應該經常使用。請參考下面的文章,它會給你很好的洞察,當你應該使用mocks:When To Mock

+0

感謝您的建議,我已經認爲可能是原因,甚至使用了絕對URL。然而,jacoco.exec文件仍然丟失... – codependent

+0

@codependet繼承人somethings我會嘗試,它可能會給我一些更多的信息,可以幫助你。如果您使用的是eclipse,請嘗試在本地運行代碼覆蓋。告訴我,如果這是工作。我發現的一件事是,默認儀器只需要在測試文件上運行。嘗試添加' \t \t \t \t \t \t \t \t **/* *測試 \t \t \t \t \t \t \t'你默認的儀器和恢復目標配置。 (如果您正在運行正常的準備代理,這也將有助於解決未來的問題)。 – Lencalot

+0

@codependent一件事我的項目在使用JaCoCo和Powermock時也需要javassist,請嘗試將其導入到maven文件依賴項中。 – Lencalot