web-dev-qa-db-fra.com

Impossible pour Jacoco de travailler avec Powermockito avec une instrumentation hors ligne

Étant donné que Jacoco ne joue pas bien avec PowerMockito lors de l’instrumentation «à la volée», j’essaie de configurer l’instrumentation hors ligne dans l’espoir que cela me permettra d’obtenir une couverture de test unitaire appropriée pour les classes qui utilisent PowerMockito.

J'ai configuré mon pom comme ci-dessous mais je ne bénéficie toujours d'aucune couverture sur ma classe de test. Toute aide très appréciée car elle me rend dingue!

<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 en test:

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

}

Je lance mvn clean install qui génère le jacoco.exe

Rapport de couverture (généré à partir de jacoco.exec à l'aide d'un script ant): -

Coverage report

28
MandyW

Ce pom a 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 this link.

14
gce

J'ai vu le même comportement, bien qu'après avoir suivi le fil de discussion sur le problème GitHub, il semble être corrigé dans 1.6.5, ce qui s'est avéré vrai pour moi.

Espérons que cela évitera un mal de tête à quelqu'un plus tard :).

Configuration de travail avec:

  • jacoco-maven-plugin 0.7.7.201606060606
  • powermock 1.6.5

Je n'utilise pas d'instrumentation hors ligne.

7
FatalError

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

Supprimez les annotations @RunWith, mettez le PowerMockRule comme décrit dans le lien ci-dessus. Rendez-le public. 

Placez la ligne suivante dans la configuration de maven-surefire-plugin:

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

(Utilisé la technique décrite ici: Puis-je utiliser le chemin d'une dépendance Maven en tant que 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
akhanna3

Je faisais également face au même problème. J'ai pu générer un rapport partiellement. J'ai utilisé ces deux balises pour mes cas de test @RunWith (PowerMockRunner.class) @ PrepareForTest ({}). Et le rapport n'était pas généré pour les cas de test où j'ai utilisé les balises mentionnées ci-dessus. Mais pour l'un des cas de test, il n'y avait que cette balise @RunWith (PowerMockRunner.class). D'une manière ou d'une autre, le rapport était généré pour ce cas. Et aussi je n'ai jamais utilisé d'instrumentation hors ligne. Lorsque j'ai essayé d'utiliser l'instrumentation hors ligne, j'ai eu une erreur en disant que la classe était déjà instrumentée. J'ai essayé divers scénarios et suivi divers liens, mais je n'ai pas pu générer le rapport. Enfin, conformément au commentaire ci-dessus, j'ai mis à niveau ma version de powermock de 1.5.5 à 1.6.5 et j'ai pu générer le rapport. Voici mon entrée pom.xml

     <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éfini comme une propriété

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

Et mis à niveau ma version de Powermock de 1.5.5 à 1.6.5. Enfin, je pouvais voir ma génération de rapports pour les classes où j’utilisais les balises suivantes dans mes cas de test @RunWith (PowerMockRunner.class) @PrepareForTest ({}) 

1
Avinash Reddy

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

0

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

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

0
Zilvinas

Utilisez l'extrait de code du plug-in maven ci-dessous, cela fonctionne très bien en Jenkins ainsi qu'en local et affiche une couverture complète du code pour les tests unitaires PowermockRunner.

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

J'ai utilisé l'instrumentation hors ligne Jacoco et, après l'exécution du test, a restauré les classes d'origine à l'aide du but "restaurer les classes instrumentées". Ma configuration 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
Ananth

Pour moi, cet échantillon de Offline Instrumentation fonctionne bien.

Mais dans mon cas, il s'avère qu'il existe une solution plus simple: n'incluez simplement pas la classe testée dans l'annotation @PrepareForTest ({}) avant sa déclaration.

0
Andriy Boyko