No se puede lograr que Jacoco trabaje con Powermockito usando instrumentación fuera de línea
(8)
Este pom funcionó para mí:
<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>
Vea this enlace.
Dado que Jacoco no juega bien con PowerMockito al instrumentar "sobre la marcha", he estado intentando configurar la instrumentación fuera de línea con la esperanza de que esto me brinde la cobertura de prueba unitaria adecuada para las clases que usan PowerMockito.
He configurado mi pom como se muestra a continuación, pero todavía tengo una cobertura del 0% en mi clase de prueba. Cualquier ayuda muy apreciada ya que me está volviendo loco, ¡loco!
<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>
Aquí está mi clase a prueba:
public class Utils {
private Utils() {
}
public static String say(String s) {
return "hello:"+s;
}
}
Aquí está mi prueba:
@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"));
}
}
Ejecuto mvn clean install que genera el jacoco.exe.
Informe de cobertura (generado desde jacoco.exec usando un script ant):
Lo hice funcionar usando el javaagent de PowerMock. Consulte aquí: https://code.google.com/p/powermock/wiki/PowerMockAgent
Elimine las anotaciones de @RunWith
, coloque la PowerMockRule como se describe en el enlace anterior. Hazlo público.
Ponga la siguiente línea en la configuración de maven-surefire-plugin:
-javaagent:${org.powermock:powermock-module-javaagent:jar}
(se utiliza la técnica descrita aquí: ¿Puedo usar la ruta a una dependencia de Maven como una propiedad? )
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.</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>
Terminé usando instrumentación fuera de línea y Jacoco (similar a lo que has hecho) en conjunto con el sonar y pude obtener los números de cobertura de eso.
Tuve el mismo problema con JaCoCo On-the-fly y PowerMock. Se generó 0% de cobertura de código cada vez.
Descubrió que la versión 0.7.7.201606060606 de JaCoCo y la versión 1.6.2 de PowerMock son compatibles y que la cobertura del código se genera con éxito.
Utilicé la instrumentación fuera de línea de Jacoco y después de la ejecución de las clases originales restauradas de prueba con la ayuda del objetivo "restaurar clases instrumentadas". Mi configuración de JaCoCo se ve así:
<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>
Utilice el siguiente fragmento de código de complemento de Maven. Esto funciona bien en Jenkins así como en local y muestra una cobertura de código completa para las pruebas de unidad 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>
Vi el mismo comportamiento, aunque después de seguir el hilo en el problema de GitHub, parece que se solucionó en 1.6.5, lo que resultó ser cierto para mí.
Esperemos que esto le ahorre a alguien un dolor de cabeza más tarde :).
Configuración de trabajo con:
- Jacoco-Maven-Plugin 0.7.7.201606060606
- powermock 1.6.5
No estoy usando la instrumentación fuera de línea.
Yo también estaba enfrentando el mismo problema. Pude generar informe parcialmente. He usado ambas etiquetas para mis casos de prueba @RunWith (PowerMockRunner.class) @PrepareForTest ({}). Y el informe no se generó para los casos de prueba en los que usé las etiquetas mencionadas anteriormente. Pero para uno de los casos de prueba solo existía esta etiqueta @RunWith (PowerMockRunner.class). De alguna manera el informe se estaba generando para ese caso. Y también nunca he usado la instrumentación fuera de línea. Cuando intenté usar la instrumentación fuera de línea, recibía un error que decía que la clase ya estaba instrumentada. Probé varios escenarios y seguí varios enlaces, pero no pude generar el informe. Finalmente, de acuerdo con el comentario anterior, actualicé mi versión de powermock de 1.5.5 a 1.6.5 y pude generar el informe. A continuación está mi entrada 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>
La siguiente es mi entrada en pom .xml para 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} se estableció como una propiedad
<properties>
<argLine>-noverify -Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=512m</argLine>
</properties>
Y actualicé mi versión powermock de 1.5.5 a 1.6.5 . Finalmente pude ver mi generación de informes para las clases en las que utilicé las siguientes etiquetas en mis casos de prueba @RunWith (PowerMockRunner.class) @PrepareForTest ({})