Impossible de faire travailler Jacoco avec Powermockito en utilisant des instruments hors ligne

étant donné que Jacoco ne joue pas bien avec PowerMockito lors de l'instrumentation "on the fly", j'ai essayé de configurer l'instrumentation hors ligne dans l'espoir que cela me donnera une couverture de test unité appropriée pour les classes qui utilisent PowerMockito.

j'ai configuré mon pom comme ci-dessous mais j'ai quand même une couverture de zéro % sur ma classe de test. Toute aide beaucoup apprécié car il me conduit lentement bonkers!

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>mandy</groupId>
    <artifactId>jacoco-test</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>jacoco-test Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <powermock.version>1.5.4</powermock.version>
        <jacoco.version>0.7.1.201405082137</jacoco.version>
    </properties>

    <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>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.version}</version>
                <executions>
                    <execution>
                        <id>instrument</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>instrument</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>restore-report</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>restore-instrumented-classes</goal>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.17</version>
                <configuration>
                    <!--<argLine>${argLine}</argLine>-->
                    <systemPropertyVariables>
                        <!-- JaCoCo runtime must know where to dump coverage: -->
                        <jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
                    </systemPropertyVariables>
                </configuration>
            </plugin>
        </plugins>
        <finalName>jacoco-test</finalName>
    </build>
</project>

voici ma classe à l'essai:

public class Utils {

    private Utils() {

    }

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

voici mon test:

@RunWith(PowerMockRunner.class)

@PrepareOnlyThisForTest(Utils.class)
@PowerMockIgnore("org.jacoco.agent.rt.*")
public class UtilsTest {

    @Test
    public void testSay() throws Exception {
        PowerMockito.mockStatic(Utils.class);
        Mockito.when(Utils.say(Mockito.anyString())).thenReturn("hello:mandy");
        assertEquals("hello:mandy", Utils.say("sid"));
    }

}

j'exécute mvn clean install qui génère le jacoco.exe

rapport de Couverture (généré à partir de jacoco.exec utilisant un script ant): -

Coverage report

26
demandé sur MandyW 2014-06-01 23:42:44

8 réponses

Cette pom fonctionné pour moi:

 <build>
    <finalName>final-name</finalName>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <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>0.7.2.201409121644</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>
            </executions>
        </plugin>
    </plugins>
</build>

voir ce lien .

13
répondu gce 2017-04-24 20:40:10

j'ai vu le même comportement, mais après avoir suivi le fil sur la question GitHub, il semble être fixé en 1.6.5, ce qui s'est avéré vrai pour moi.

j'espère que cela va sauver quelqu'un d'un mal de tête plus tard :).

configuration de travail avec:

  • jacoco-maven-plugin 0.7.7.2016060606
  • powermock 1.6.5

Je n'utilise pas d'instrumentation hors ligne.

7
répondu FatalError 2016-10-24 22:02:33

Je l'ai fait fonctionner en utilisant le javaagent de PowerMock. voir ici: https://code.google.com/p/powermock/wiki/PowerMockAgent

supprimer les @RunWith annotations, mettre le PowerMockRule comme décrit dans le lien ci-dessus. Le rendre public.

mettre la ligne suivante dans la configuration maven-surefire-plugin:

-javaagent:${org.powermock:powermock-module-javaagent:jar}

(a utilisé la technique décrite ici : puis-je utiliser le chemin vers une dépendance Maven comme propriété? )

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.stackoverflow</groupId>
    <artifactId>q2359872</artifactId>
    <version>2.0-SNAPSHOT</version>
    <name>q2359872</name>

    <properties>
        <!-- Must be listed in the dependencies section otherwise it will be null. -->
        <my.lib>${org.jmockit:jmockit:jar}</my.lib>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.jmockit</groupId>
            <artifactId>jmockit</artifactId>
            <version>1.11</version>
        </dependency>
    </dependencies>
    <build>
        <defaultGoal>generate-sources</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>properties</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- Example usage: -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <phase>generate-sources</phase>
                    </execution>
                </executions>
                <configuration>
                    <executable>echo</executable>
                    <arguments>
                        <argument>path to jar=</argument>
                        <argument>${org.jmockit:jmockit:jar}</argument>
                        <argument>my.lib=</argument>
                        <argument>${my.lib}</argument>
                    </arguments>
                </configuration>
            </plugin>
            <!-- end of Example usage -->
        </plugins>
    </build>
</project> 
1
répondu akhanna3 2017-05-23 12:09:55

j'étais également confronté à la même question. J'ai pu générer du rapport en partie. J'ai utilisé ces deux étiquettes pour mes cas de test @RunWith (PowerMockRunner.classe) @PrepareForTest ({}). Et le rapport n'était pas généré pour les cas de test où j'ai utilisé les étiquettes mentionnées ci-dessus. Mais pour l'un des cas d'essai il n'y avait que cette étiquette @RunWith(PowerMockRunner.classe.) D'une façon ou d'une autre, le rapport était généré pour cette affaire. Et je n'ai jamais utilisé d'instrumentation hors ligne. Quand j'ai essayé en utilisant l'instrumentation hors ligne, je me suis trompé en disant que la classe était déjà instrumentée. J'ai essayé divers scénarios et suivi divers liens mais n'ai pas pu générer le rapport. Enfin, conformément au commentaire ci-dessus, j'ai mis à jour ma version de powermock de 1.5.5 à 1.6.5 et j'ai pu générer le rapport. Voici mon pom.xml entrée

     <plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.5.201505241946</version>
    <executions>
        <execution>
            <id>pre-unit-test</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
             <configuration>
                    <!-- Sets the path to the file which contains the execution data. -->
                    <destFile>${basedir}/target/jacoco.exec</destFile>
                    <!--
                        Sets the name of the property containing the settings
                        for JaCoCo runtime agent.
                    -->
            </configuration>
        </execution>
        <execution>
            <!--<id>post-unit-test</id>
            <phase>test</phase>-->
            <id>default-report</id>
            <phase>verify</phase>
            <goals>
                <goal>report</goal>
            </goals>
              <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <dataFile>${basedir}/target/jacoco.exec</dataFile>
                <!-- Sets the output directory for the code coverage report. -->
                <outputDirectory>${basedir}/target/jacoco-ut</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

Voici mon entrée dans pom .xml pour maven-surefire-plugin

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
            <argLine>@{argLine}</argLine>
            <skipTests>false</skipTests>
            <testFailureIgnore>true</testFailureIgnore>
        </configuration>
    </plugin>

@{argLine} a été définie comme une propriété

<properties>
    <argLine>-noverify -Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=512m</argLine>
</properties>

et mis à jour ma version powermock de 1.5.5 à 1.6.5 . Enfin je pouvais voir ma génération de rapport pour les classes où j'ai utilisé les tags suivants dans Mes cas de test @RunWith (PowerMockRunner.classe) @PrepareForTest ({})

1
répondu Avinash Reddy 2017-06-16 11:47:03

j'ai fini par utiliser des instruments hors ligne et Jacoco (similaire à ce que vous avez fait) en conjonction avec sonar et j'ai pu obtenir les numéros de couverture à partir de cela.

0
répondu Ashwin Krishnamurthy 2015-10-26 23:28:44

j'ai utilisé L'instrumentation hors ligne de Jacoco et après l'exécution de l'essai restauré classes originales avec l'aide de" restaurer-instrumented-classes " objectif. Ma configuration de JaCoCo ressemble à ceci:

 <plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.9</version>
    <executions>
      <execution>
        <id>default-prepare-agent</id>
        <goals>
          <goal>prepare-agent</goal>
        </goals>
      </execution>
      <execution>
        <id>jacoco-instrument</id>
        <goals>
          <goal>instrument</goal>
        </goals>
      </execution>
      <execution>
        <id>jacoco-restore-instrumented-classes</id>
        <goals>
          <goal>restore-instrumented-classes</goal>
        </goals>
      </execution>
      <execution>
        <id>jacoco-report</id>
        <phase>package</phase>
        <goals>
          <goal>report</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <excludes>
        <exclude>*</exclude>
      </excludes>
    </configuration>
  </plugin>
0
répondu Ananth 2018-03-01 12:44:39

J'ai eu le même problème avec JaCoCo on-the-fly et PowerMock. 0% couverture de code a été générée à chaque fois

a découvert que la version 0.7.7.2016060606 de JaCoCo et la version 1.6.2 de PowerMock sont compatibles et que la couverture du code est générée avec succès.

0
répondu Zilvinas 2018-03-23 10:37:01

utilisation ci-dessous code de plugin maven snippet cela fonctionne très bien à jenkins ainsi que dans les locaux et montre une couverture complète du code pour PowermockRunner tests unitaires

<build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>${jacoco-maven-plugin.version}</version>
                    <executions>
                        <execution>
                            <id>pre-test</id>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                            <configuration>
                                <append>true</append>                           
                            </configuration>
                        </execution>
                        <execution>
                            <id>pre-integ-test</id>
                            <goals>
                                <goal>prepare-agent-integration</goal>
                            </goals>
                            <configuration>
                                <append>true</append>                           
                            </configuration>
                        </execution>

                        <execution>
                            <id>jacoco-instrument</id>
                            <goals>
                                <goal>instrument</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>jacoco-restore-instrumented-classes</id>
                            <goals>
                                <goal>restore-instrumented-classes</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <excludes>
                            <exclude>*</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
0
répondu Vashishtkumar Balagannavar 2018-04-12 06:46:23