Classpath顺序因JUnit runner而异

时间:2014-04-10 12:27:40

标签: java maven junit classpath

我遇到的问题看起来类似于this question中暴露的问题,但我认为不同,希望更容易解决。

我有一个测试TestMyClass的单元测试类MyClass,而MyClass恰好有一个对log4j记录器的静态引用。

当我使用TestMyClas运行@RunWith(MockitoJUnitRunner.class)时,记录器的初始化就可以了。但是当我使用@RunWith(PowerMockRunner.class)运行测试时,log4j会在初始化记录器时记录以下错误:

  

log4j:错误A" org.apache.log4j.xml.DOMConfigurator"对象不能分配给" org.apache.log4j.spi.Configurator"变量。
  log4j:错误类" org.apache.log4j.spi.Configurator"被装载   log4j:ERROR [org.powermock.core.classloader.MockClassLoader@1ad186f]而对象类型为
  log4j:ERROR" org.apache.log4j.xml.DOMConfigurator"由[sun.misc.Launcher$AppClassLoader@13f5d07]加载   log4j:错误无法实例化配置程序[org.apache.log4j.xml.DOMConfigurator]。

我发现发生这种情况是因为以下代码段在log4j初始化代码中返回false

Configurator.class.isAssignableFrom(DOMConfigurator.class)

这应该是真的,DomConfigurator实现Configurator,但我认为它返回false,因为我碰巧在类路径上有这两个版本的类:一个来自log4j-1.2.14,一个来自log4j的,额外-1.1。我想当使用PowerMockRunner运行测试时,这两个类不会从同一个jar中加载(如果可能还有其他原因,请告诉我。)

所以我想理解:

  • 为什么我要面对这个问题?为什么classpath顺序因使用的JUnit运行程序而异?它不应该是确定性的吗?
  • 有没有办法解决这个问题?

N.B。:我必须使用PowerMockRunner,因为我需要模拟静态调用。我无法摆脱其中一个log4j jar,因为它们都是我项目依赖项的依赖项。这个问题不会使我的测试失败,它只是打印出这些错误,但仍然很好解决它。

1 个答案:

答案 0 :(得分:3)

我不再记得我们为什么必须这样做,但是我们使用PowerMock来模拟静态方法的测试类之一在@PrepareForTest注释的右上方有这个:

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

PowerMock FAQ中的数字5给出了为什么需要这样做的几个原因,并提出了其他解决方案。忽略log4j对我们有用。

P.S。我们正在使用PowerMock 1.5.1。