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 TestMyClas
s 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.