Frage

I am facing a problem that looks similar to the one exposed in this question, but I think different and hopefully easier to solve.

I have a unit test class TestMyClass that tests MyClass, and MyClass happens to have a static reference to a log4j logger.

When I run TestMyClass with@RunWith(MockitoJUnitRunner.class), the initialization of the logger goes fine. But when I run the test with @RunWith(PowerMockRunner.class), the following error is logged by log4j while initializing the logger:

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@1ad186f] whereas object of type
log4j:ERROR "org.apache.log4j.xml.DOMConfigurator" was loaded by [sun.misc.Launcher$AppClassLoader@13f5d07].
log4j:ERROR Could not instantiate configurator [org.apache.log4j.xml.DOMConfigurator].

I found out that this happens because the following snippet returns false in the log4j initialization code:

Configurator.class.isAssignableFrom(DOMConfigurator.class)

This should be true, DomConfigurator implements Configurator, but I think it returns false because I happen to have two versions of these classes on the classpath: one from log4j-1.2.14 and one from log4j-extras-1.1. And I suppose that when the test is run with PowerMockRunner, the two classes are not loaded from the same jar (let me know if there could be another reason).

So I would like to understand:

  • Why do I face this issue? Why does the classpath order differs depending on the JUnit runner used? Isn't it supposed to be deterministic?
  • Is there any way to get around this?

N.B.: I have to use PowerMockRunner, because I need to mock a static call. I cannot get rid of one of the log4j jars, because both of them are dependencies of a dependency of my project. This issue does not make my tests fail, it just prints those errors, but still it would be nice to have it solved.

War es hilfreich?

Lösung

I no longer remember exactly why we had to do this, however one of the test classes where we use PowerMock to mock static methods has this at the top, right under the @PrepareForTest annotation:

@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.commons.logging.*" })

Number 5 in the PowerMock FAQ gives several reasons why this might be needed, and suggests other solutions. Ignoring log4j worked for us.

P.S. We are using PowerMock 1.5.1.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top