Skip to content
Arthur Zagretdinov edited this page May 1, 2016 · 19 revisions

Frequently asked questions

  1. PowerMockRunner throws a
      java.lang.NoClassDefFoundError: org/junit/internal/runners/BeforeAndAfterRunner
    or
    java.lang.SecurityException: class "org.junit.internal.runners.TestClass"'s signer information does not match signer information of other classes in the same package
    exception. What's wrong?
    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 to org.powermock.modules.junit4.legacy.PowerMockRunner or vice versa. Look at the getting started guide to see how to configure this in maven.
  2. Cobertura gives me errors or produces strange results when running PowerMock tests in Maven, how do I solve this?
    Either:
    1. Upgrade to Cobertura 2.4+ or,
    2. Follow the instructions on this blog or,
    3. Add the following to your pom.xml file:
      
      <build>
      <plugins>
      <plugin>
      <artifactId>maven-surefire-plugin</artifactId>
      <configuration>
      <forkMode>pertest</forkMode>
      </configuration>
      </plugin>
      </plugins>
      </build>
  3. 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.
  4. 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.
  5. 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.
  6. When running a PowerMock test log4j gives me the following (or something similar) error, what now?
    log4j: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].
    or
    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:
    1. Upgrade to PowerMock 1.3+
    2. 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.*").
    3. Add -Dlog4j.ignoreTCL=true as VM-Arguments to your test-run-configuration.
    4. 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 {

      }
    5. 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 the org.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);
      ...
      }
      ...
      }
    6. 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);
      ...
      }
      ...
      }
    7. You could try using the @PrepareEverythingForTest annotation (not recommended).
  7. Does PowerMock work with TestNG?
    Yes, since version 1.3.5 PowerMock does have basic TestNG support.
  8. Is PowerMock a fork of EasyMock?
    No. PowerMock extends other mock frameworks such as EasyMock with powerful capabilities such as static mocking.
  9. Can you use PowerMock with other frameworks that uses a JUnit runner?
    Yes, you can make use of the PowerMockRule.
  10. 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>
  11. 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.