我有一个较大的Maven多项目构建,单元测试主要使用PowerMock,版本1.6.2.我决定整合JaCoCo,因此我们可以开始发布我们的代码覆盖率指标.最新版本的JaCoCo,0.7.8,需要PowerMock 1.6.6,所以我升级了我的版本.
我现在看到一些关于“whenNew”调用的错误行为,该调用在代码库的整个测试中重复出现.
有问题的“whenNew()”调用如下所示:
PowerMockito.whenNew(BlahBlah.class)
.withArguments(any(SomeClass.class))
.thenReturn(blahBlahInstance);
使用PowerMock 1.6.2,这工作正常.当我升级到1.6.6时,为了完成这项工作,我不得不进行两次更改,一次是可以接受的但很烦人(因为我不知道为什么需要它),而另一种真的是不可接受的.
可接受的更改是在类顶部的“@PrepareForTest”注释.使用PowerMock 1.6.2,这只用于列出调用“new BlahBlah(…)”的类,并且工作正常.为了使这个工作(除了下一个更改),我还必须将“BlahBlah.class”添加到该列表中.我可以接受这一点,但如果我对该列表的确切内容有一些明确的指示,那将会非常有帮助.
第二个不可接受的变化是我必须将“.withArguments(any(SomeClass.class))”更改为“.withAnyArguments()”.我也试过“withArguments(anyObject())”,但也无法工作.
更新:
请注意,我使用的是mockito-core版本1.10.19.我从https://github.com/powermock/powermock/wiki/MockitoUsage#supported-versions看到,PowerMock 1.6.6(1.6.2)支持该版本的mockito-core.
最佳答案 首先是关于你的陈述
The latest version of JaCoCo, 0.7.8, requires PowerMock 1.6.6
JaCoCo不需要PowerMock,JaCoCo 0.7.8对PowerMock没有什么特别之处.截至今日,0.7.8是JaCoCo的最新发布版本.
我猜你的陈述是一种误解,来自阅读https://github.com/powermock/powermock/wiki/Code-coverage-with-JaCoCo,其中指出
JaCoCo Offline Instrumentation works only with PowerMock version 1.6.6 and upper.
根据https://github.com/powermock/powermock/blob/master/changelog.txt
Change log 1.6.6 (2016-11-04)
- Fixed #645 jacoco offline instrumentation incompatibility with powermock byte-code manipulation when using @SuppressStaticInitializationFor
即只针对一个特定情况进行修复.在其他情况下,早期版本的PowerMock已经使用离线检测与早期版本的JaCoCo一起使用.
然后根据您对PowerMock升级到1.6.6之后的状态描述,但在其他更改之前,尝试创建Minimal, Complete, and Verifiable example:
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<powermock.version>1.6.6</powermock.version>
<jacoco.version>0.7.8</jacoco.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</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>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<classifier>runtime</classifier>
<version>${jacoco.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<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>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
的src /主/ JAVA /组织/示例/ BlahBlah.java:
package org.example;
public class BlahBlah {
private final SomeClass c;
public BlahBlah(SomeClass c) {
this.c = c;
}
public String run() {
return c.toString();
}
}
的src /主/ JAVA /组织/示例/ SomeClass.java:
package org.example;
public class SomeClass {
private final String s;
public SomeClass(String s) {
this.s = s;
}
@Override
public String toString() {
return s;
}
}
的src /主/ JAVA /组织/示例/ Example.java:
package org.example;
public class Example {
public String fun() {
return new BlahBlah(new SomeClass("Hello World")).run();
}
}
的src /测试/ JAVA /组织/示例/ ExampleTest.java:
package org.example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
@PrepareForTest({Example.class})
@RunWith(PowerMockRunner.class)
public class ExampleTest {
@Test
public void test() throws Exception {
BlahBlah e = new BlahBlah(new SomeClass("Hello PowerMock"));
PowerMockito.whenNew(BlahBlah.class)
.withArguments(any(SomeClass.class))
.thenReturn(e);
assertEquals("Hello PowerMock", new Example().fun());
}
}
和
mvn clean verify
工作得很好.所以在你的描述中应该有一些其他东西可以真正重现你的情况.希望这有点帮助,至少建立一个基于此的更好的再现器.
另外:尝试将JaCoCo的集成过程与PowerMock的升级分离 – 可能只是这种升级存在问题,而不是JaCoCo的集成.