-
Notifications
You must be signed in to change notification settings - Fork 586
FAQ
Arthur Zagretdinov edited this page May 1, 2016
·
19 revisions
- PowerMockRunner throws a
orjava.lang.NoClassDefFoundError: org/junit/internal/runners/BeforeAndAfterRunner
exception. What's wrong?java.lang.SecurityException: class "org.junit.internal.runners.TestClass"'s signer information does not match signer information of other classes in the same package
You're probably using the wrong PowerMockRunner. There's one runner made for JUnit 4.4 and above and a second runner made for JUnit 4.0-4.3 (although the latter also works for some older minor versions of JUnit 4.4). Try switching from the
org.powermock.modules.junit4.PowerMockRunner
toorg.powermock.modules.junit4.legacy.PowerMockRunner
or vice versa. Look at the getting started guide to see how to configure this in maven. - Cobertura gives me errors or produces strange results when running PowerMock tests in Maven, how do I solve this?
Either:
- Upgrade to Cobertura 2.4+ or,
- Follow the instructions on this blog or,
- Add the following to your pom.xml file:
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>pertest</forkMode>
</configuration>
</plugin>
</plugins>
</build>
- Upgrade to Cobertura 2.4+ or,
- I get a ClassCastException from DocumentBuilderFactory, SaxParserFactory or other XML related classes
The reason is that the XML framework tries to instantiate classes using reflection and does this from the thread context classloader (PowerMock's classloader) but then tries to assign the created object to a field not loaded by the same classloader. When this happens you need to make use of the @PowerMockIgnore annotation to tell PowerMock to defer the loading of a certain package to the system classloader. What you need to ignore is case specific but usually it's the XML framework or some packages that interact with it. E.g.
@PowerMockIgnore({"org.xml.*", "javax.xml.*"})
. Another option would be to try to bootstrap using our Java Agent.
- I cannot mock classes in from
java.lang
,java.net
,java.io
or other system classes, why?
This is because they're loaded by Java's bootstrap classloader and cannot be byte-code manipulated by PowerMock's classloader. Since PowerMock 1.2.5 there's a work-around, please have a look at this simple example to see how it's done.
- When mocking Hibernate you get an error similar to:
java.lang.ClassCastException: org.hibernate.ejb.HibernatePersistence cannot be cast to javax.persistence.spi.PersistenceProvider
at javax.persistence.Persistence.findAllProviders(Persistence.java:80)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:49)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:34)
...
Solution: Upgrade to PowerMock 1.3+ or use
@PowerMockIgnore("javax.persistence.*")
at the class-level of your test.
- When running a PowerMock test log4j gives me the following (or something similar) error, what now?
orlog4j:ERROR A "org.apache.log4j.xml.DOMConfigurator" object is not
assignable to a "org.apache.log4j.spi.Configurator" variable.
log4j:ERROR The class "org.apache.log4j.spi.Configurator" was loaded
by
log4j:ERROR [org.powermock.core.classloader.MockClassLoader@14a55f2]
whereas object of type
log4j:ERROR "org.apache.log4j.xml.DOMConfigurator" was loaded by
[sun.misc.Launcher$AppClassLoader@92e78c].
log4j:ERROR Could not instantiate configurator
[org.apache.log4j.xml.DOMConfigurator].
Caused by: org.apache.commons.logging.LogConfigurationException:
Invalid class loader hierarchy. You have more than one version of
'org.apache.commons.logging.Log' visible, which is not allowed.
There are a couple of different solutions to this:
- Upgrade to PowerMock 1.3+
- Make use of the @PowerMockIgnore annotation at the class-level of the test. For example if using log4j, use
@PowerMockIgnore("org.apache.log4j.*")
if using commons logging, use@PowerMockIgnore("org.apache.commons.logging.*")
.
- Add
-Dlog4j.ignoreTCL=true
as VM-Arguments to your test-run-configuration.
- If you're using PowerMock 1.1 or above you should use the
@MockPolicy
annotation and specify a mock policy. For example if you're using slf4j in combination with log4j use@MockPolicy(Slf4jMockPolicy.class)
or if you're using Log4j stand-alone use@MockPolicy(Log4jMockPolicy.class)
. This is the recommended way. For example:
@RunWith(PowerMockRunner.class)
@MockPolicy(Log4jMockPolicy.class)
public class MyTest {
}
- Create a nice mock of the Logger class and set the the Logger field to this instance. If the field is static suppress the static initializer for the class (using the
@SuppressStaticInitializerFor
annotation) and then set the logger field to the mock you just created. Next prepare theorg.apache.log4j.Appender
for testing using the @PrepareForTest annotation. For example:
@RunWith(PowerMockRunner.class)
@SuppressStaticInitializationFor("org.myapp.MyClassUsingLog4J")
@PrepareForTest( { Appender.class })
public class MyTest {
@Before
public void setUp() {
Logger loggerMock = createNiceMock(Logger.class);
Whitebox.setInternalState(MyClassUsingLog4J.class, loggerMock);
...
}
...
}
- Follow the same procedure as in the previous step but instead of adding the
org.apache.log4j.Appender
class to the@PrepareForTest
annotation you add"org.apache.log4j.LogManager"
to the@SuppressStaticInitializerFor
annotation. For example:
@RunWith(PowerMockRunner.class)
@SuppressStaticInitializationFor( {
"org.myapp.MyClassUsingLog4J",
"org.apache.log4j.LogManager" })
public class MyTest {
@Before
public void setUp() {
Logger loggerMock = createNiceMock(Logger.class);
Whitebox.setInternalState(MyClassUsingLog4J.class, loggerMock);
...
}
...
}
- You could try using the
@PrepareEverythingForTest
annotation (not recommended).
- Upgrade to PowerMock 1.3+
- Does PowerMock work with TestNG?
Yes, since version 1.3.5 PowerMock does have basic TestNG support.
- Is PowerMock a fork of EasyMock?
No. PowerMock extends other mock frameworks such as EasyMock with powerful capabilities such as static mocking.
- Can you use PowerMock with other frameworks that uses a JUnit runner?
Yes, you can make use of the PowerMockRule.
- I'm using the Java Agent and Java 7 run into errors like "Unable to load Java agent", what to do?
You can try the following work-around:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14</version>
<configuration>
<argLine>-javaagent:${settings.localRepository}/org/powermock/powermock-module-javaagent/${powermock.version}/powermock-module-javaagent-${powermock.version}.jar -XX:-UseSplitVerifier</argLine>
</configuration>
</plugin>
- I have upgraded to release 1.6.5 and PowerMock has started throwing exception:
.
Extension API internal error: org.powermock.api.extension.reporter.MockingFrameworkReporterFactoryImpl could not be located in classpath.
If you use Maven, please add the following to your pom.xml
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito-common</artifactId> <version>1.6.5</version> </dependency>
If you download full jar, then, please, download one more jar from Maven Central Repository and add it to your classpath.