org.slf4j.helpers.SubstituteLogger 无法转换为 ch.qos.logback.classic.Logger

org.slf4j.helpers.SubstituteLogger cannot be cast to ch.qos.logback.classic.Logger

我见过一些与这个问题非常相似的问题 (like this one),但其中 none 个得到了很好的答案,或者至少有一个解释或解决了这个问题

我能够创建一个非常小的项目(基本上是 2 个 Scala 类 - 每个都有一个记录器 - 和 2 个测试 类),其结构与我发现的真实项目相似问题。该示例可在此处获得:project example

问题出现在我运行sbt test的时候,导致如下错误:

{14:43:41} (#47) ~/Desktop/logger-exp/log-exp@pedrorijo(master) $ sbt test
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=384m; support was removed in 8.0
[info] Loading global plugins from /Users/pedrorijo/.sbt/0.13/plugins
[info] Loading project definition from /Users/pedrorijo/Desktop/git/scala/logger-exp/log-exp/project
[info] Set current project to log-exp (in build file:/Users/pedrorijo/Desktop/git/scala/logger-exp/log-exp/)
[info] HelloTest:
[info] Exception encountered when attempting to run a suite with class name: HelloTest *** ABORTED ***
[info]   java.lang.ExceptionInInitializerError:
[info]   at HelloTest$$anonfun.apply$mcV$sp(HelloTest.scala:8)
[info]   at HelloTest$$anonfun.apply(HelloTest.scala:8)
[info]   at HelloTest$$anonfun.apply(HelloTest.scala:8)
[info]   at org.scalatest.Transformer$$anonfun$apply.apply$mcV$sp(Transformer.scala:22)
[info]   at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
[info]   at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:22)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:20)
[info]   at org.scalatest.FunSuiteLike$$anon.apply(FunSuiteLike.scala:166)
[info]   at org.scalatest.Suite$class.withFixture(Suite.scala:1122)
[info]   ...
[info]   Cause: java.lang.ClassCastException: org.slf4j.helpers.SubstituteLogger cannot be cast to ch.qos.logback.classic.Logger
[info]   at com.example.Hello$.<init>(Hello.scala:8)
[info]   at com.example.Hello$.<clinit>(Hello.scala)
[info]   at HelloTest$$anonfun.apply$mcV$sp(HelloTest.scala:8)
[info]   at HelloTest$$anonfun.apply(HelloTest.scala:8)
[info]   at HelloTest$$anonfun.apply(HelloTest.scala:8)
[info]   at org.scalatest.Transformer$$anonfun$apply.apply$mcV$sp(Transformer.scala:22)
[info]   at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
[info]   at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:22)
[info]   at org.scalatest.Transformer.apply(Transformer.scala:20)
[info]   ...
SLF4J: The following set of substitute loggers may have been accessed
SLF4J: during the initialization phase. Logging calls during this
SLF4J: phase were not honored. However, subsequent logging calls to these
SLF4J: loggers will work as normally expected.
SLF4J: See also http://www.slf4j.org/codes.html#substituteLogger
SLF4J: com.example.Hello$
14:43:52.846 [pool-6-thread-4-ScalaTest-running-WorldTest] INFO  com.example.World$ - LOGGING
[info] WorldTest:
[info] - test
[info] Run completed in 456 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 1
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] *** 1 SUITE ABORTED ***
[error] Error during tests:
[error]     HelloTest
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 1 s, completed Aug 2, 2015 2:43:52 PM

但如果我 运行 每个测试单独通过:

sbt "testOnly HelloTest"sbt "testOnly WorlTest" 我没有收到任何错误。

据我所知,这不仅仅是 Scala 的问题,在 Java 中似乎也有可能发生。此外,我读到在初始化期间记录器被替换为 Substitute Logger.

但是我看不懂:

  1. 为什么它只发生在测试中,而当 运行同时进行两个测试时?
  2. 为什么会这样?
  3. 如何debug/solve这个问题?

As I said before, I've created a repository with a working example (working, meaning with the error happening) here: project example

看来问题出在以下语句中:

val logger = LoggerFactory.getLogger(X.getClass).asInstanceOf[Logger]

我在某处找到了这种获取记录器的方法,所以我从来没有想过问题可能出在这一行上。 final 方法是不必要的,它是错误原因。为了停止出现所描述的错误,我删除了强制转换,将之前的表达式替换为:

val logger = LoggerFactory.getLogger(X.getClass)