java.lang.NoSuchFieldError cuando se usa ScalaTest

Sep 20 2020

Recibo un error bastante difícil de depurar cuando uso ScalaTest. Curiosamente, esto parece ocurrir cuando mi programa no tiene un objeto Main, pero no cuando tiene un objeto Main. Mi código en realidad solo usa una clase de tipos con un método polimórfico para obtener un segmento de una lista, y se ve así (disculpas por el ejemplo ligeramente detallado, lo he reducido tanto como puedo):

package sportarray

object ArrayDefs {
  abstract class IsArr[A, I0, DT] {
    def getElem(self: A, i: Int): DT
    def getSlice[R](self: A, r: R)(implicit sliceTc: IsSlice[R]): sliceTc.Out = sliceTc.getSlice(self, r)

    trait IsSlice[R] {
      type Out
      def getSlice(self: A, ref: R): Out 
    }
    object IsSlice {
      implicit val iLocTCForInt = new IsSlice[Int] { 
        type Out = DT
        def getSlice(self: A, ref: Int): Out = getElem(self, ref)
      }
      implicit val iLocTCForList = new IsSlice[List[Int]] { 
        type Out = List[DT]
        def getSlice(self: A, ref: List[Int]): Out = ref.map(getElem(self, _))
      }
    }
  }

  object IsArrSyntax {
    implicit class IsArrOps[A, I0, T](self: A)(implicit 
      tc1d: IsArr[A, I0, T]
    ) {
      def getElem(i: Int) = tc1d.getElem(self, i)
      def getSlice[R](r: R)(implicit sliceTc: tc1d.IsSlice[R]) = tc1d.getSlice(self, r)
    }
  }
}

object ListOfListsObj {
  import ArrayDefs._
  case class List1d[I0, T] (
    indices: List[I0],
    data: List[T],
  )
  implicit def list1dIs1dSpArr[A, I0, T] = 
    new IsArr[List1d[I0, T], I0, T] {
      def getElem(self: List1d[I0, T], i: Int) = self.data(i)
    }
}

Mi prueba es simple y se ve así, en su propio archivo en el directorio de prueba:

package sportarray

import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class ArraySpec extends AnyFlatSpec with Matchers {
  "List" should "act as an array" in {
    import ArrayDefs._
    import ArrayDefs.IsArrSyntax._
    import ListOfListsObj._
    val list1d = List1d[Int, Double](List(1,2,3), List(1.0, 2.0, 3.0))
    assert(list1d.getSlice(1) == 2.0)
  }
}

Si veo sbt testeste código como está, aparece el siguiente error:

java.lang.NoSuchFieldError: sportarray$ArrayDefs$IsArrSyntax$IsArrOps$$tc1d
at sportarray.ArraySpec.$anonfun$new$1(HelloSpec.scala:12) at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85) at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) at org.scalatest.Transformer.apply(Transformer.scala:22) at org.scalatest.Transformer.apply(Transformer.scala:20) at org.scalatest.flatspec.AnyFlatSpecLike$$anon$5.apply(AnyFlatSpecLike.scala:1683)

Luego intenté agregar una clase principal al programa para ver si esto era un problema con la prueba o un problema con el código en sí:

object Main extends App {
  import ArrayDefs._
  import ArrayDefs.IsArrSyntax._
  import ListOfListsObj._
  val list1d = List1d[Int, Double](List(1,2,3), List(1.0, 2.0, 3.0))
  assert(list1d.getSlice(1) == 2.0)
}

Esto funciona bien si yo sbt run, y, curiosamente, también me permite ejecutar sbt testsin ningún problema. Si luego elimino esta clase principal, sbt testuna vez más falla. ¿Alguien puede arrojar algo de luz sobre lo que está sucediendo aquí?

¡Gracias por cualquier ayuda!

Respuestas

2 DmytroMitin Sep 21 2020 at 21:03

En realidad, ejecuté Scalatest desde la línea de comando y tuvo éxito

$ scalac -cp .:scalactic_2.13-3.2.2.jar:scalatest_2.13-3.2.2.jar:scalatest-core_2.13-3.2.2.jar:scalatest-flatspec_2.13-3.2.2.jar:scalatest-matchers-core_2.13-3.2.2.jar:scalatest-shouldmatchers_2.13-3.2.2.jar:scalatest-compatible-3.2.2.jar App.scala AppTest.scala $ scala -cp .:scalactic_2.13-3.2.2.jar:scalatest_2.13-3.2.2.jar:scalatest-core_2.13-3.2.2.jar:scalatest-flatspec_2.13-3.2.2.jar:scalatest-matchers-core_2.13-3.2.2.jar:scalatest-shouldmatchers_2.13-3.2.2.jar:scalatest-compatible-3.2.2.jar:scala-xml_2.13-1.3.0.jar org.scalatest.run AppTest
Run starting. Expected test count is: 1
AppTest:
List
- should act as an array
Run completed in 151 milliseconds.
Total number of tests run: 1
Suites: completed 1, aborted 0
Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
All tests passed.

mientras que en IntelliJ y sbt falló:

(IntelliJ)

An exception or error caused a run to abort: App$ArrayDefs$IsArrSyntax$IsArrOps$$tc1d
java.lang.NoSuchFieldError: App$ArrayDefs$IsArrSyntax$IsArrOps$$tc1d
    at AppTest.$anonfun$new$1(AppTest.scala:10) at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85) at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
    at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) at org.scalatest.Transformer.apply(Transformer.scala:22) at org.scalatest.Transformer.apply(Transformer.scala:20) at org.scalatest.flatspec.AnyFlatSpecLike$$anon$5.apply(AnyFlatSpecLike.scala:1683) at org.scalatest.TestSuite.withFixture(TestSuite.scala:196) at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
    at org.scalatest.flatspec.AnyFlatSpec.withFixture(AnyFlatSpec.scala:1685)
    at org.scalatest.flatspec.AnyFlatSpecLike.invokeWithFixture$1(AnyFlatSpecLike.scala:1681) at org.scalatest.flatspec.AnyFlatSpecLike.$anonfun$runTest$1(AnyFlatSpecLike.scala:1693)
    at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306)
    at org.scalatest.flatspec.AnyFlatSpecLike.runTest(AnyFlatSpecLike.scala:1693)
    at org.scalatest.flatspec.AnyFlatSpecLike.runTest$(AnyFlatSpecLike.scala:1675) at org.scalatest.flatspec.AnyFlatSpec.runTest(AnyFlatSpec.scala:1685) at org.scalatest.flatspec.AnyFlatSpecLike.$anonfun$runTests$1(AnyFlatSpecLike.scala:1751)
    at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:413) at scala.collection.immutable.List.foreach(List.scala:333) at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401)
    at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:390)
    at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:427) at scala.collection.immutable.List.foreach(List.scala:333) at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401)
    at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:396)
    at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:475)
    at org.scalatest.flatspec.AnyFlatSpecLike.runTests(AnyFlatSpecLike.scala:1751)
    at org.scalatest.flatspec.AnyFlatSpecLike.runTests$(AnyFlatSpecLike.scala:1750) at org.scalatest.flatspec.AnyFlatSpec.runTests(AnyFlatSpec.scala:1685) at org.scalatest.Suite.run(Suite.scala:1112) at org.scalatest.Suite.run$(Suite.scala:1094)
    at org.scalatest.flatspec.AnyFlatSpec.org$scalatest$flatspec$AnyFlatSpecLike$$super$run(AnyFlatSpec.scala:1685) at org.scalatest.flatspec.AnyFlatSpecLike.$anonfun$run$1(AnyFlatSpecLike.scala:1796)
    at org.scalatest.SuperEngine.runImpl(Engine.scala:535)
    at org.scalatest.flatspec.AnyFlatSpecLike.run(AnyFlatSpecLike.scala:1796)
    at org.scalatest.flatspec.AnyFlatSpecLike.run$(AnyFlatSpecLike.scala:1794) at org.scalatest.flatspec.AnyFlatSpec.run(AnyFlatSpec.scala:1685) at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:45) at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13(Runner.scala:1320) at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13$adapted(Runner.scala:1314)
    at scala.collection.immutable.List.foreach(List.scala:333)
    at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:1314) at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24(Runner.scala:993) at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24$adapted(Runner.scala:971)
    at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:1480) at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:971)
    at org.scalatest.tools.Runner$.run(Runner.scala:798)
    at org.scalatest.tools.Runner.run(Runner.scala)
    at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2or3(ScalaTestRunner.java:40)
    at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:27)

(sbt)

[error] java.lang.NoSuchFieldError: App$ArrayDefs$IsArrSyntax$IsArrOps$$tc1d [error] at AppTest.$anonfun$new$1(AppTest.scala:10)
[error]     at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
[error]     at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83) [error] at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[error]     at org.scalatest.Transformer.apply(Transformer.scala:22)
[error]     at org.scalatest.Transformer.apply(Transformer.scala:20)
[error]     at org.scalatest.flatspec.AnyFlatSpecLike$$anon$5.apply(AnyFlatSpecLike.scala:1683)
[error]     at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
[error]     at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195) [error] at org.scalatest.flatspec.AnyFlatSpec.withFixture(AnyFlatSpec.scala:1685) [error] at org.scalatest.flatspec.AnyFlatSpecLike.invokeWithFixture$1(AnyFlatSpecLike.scala:1681)
[error]     at org.scalatest.flatspec.AnyFlatSpecLike.$anonfun$runTest$1(AnyFlatSpecLike.scala:1693) [error] at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306) [error] at org.scalatest.flatspec.AnyFlatSpecLike.runTest(AnyFlatSpecLike.scala:1693) [error] at org.scalatest.flatspec.AnyFlatSpecLike.runTest$(AnyFlatSpecLike.scala:1675)
[error]     at org.scalatest.flatspec.AnyFlatSpec.runTest(AnyFlatSpec.scala:1685)
[error]     at org.scalatest.flatspec.AnyFlatSpecLike.$anonfun$runTests$1(AnyFlatSpecLike.scala:1751) [error] at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:413)
[error]     at scala.collection.immutable.List.foreach(List.scala:333)
[error]     at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401) [error] at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:390) [error] at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:427)
[error]     at scala.collection.immutable.List.foreach(List.scala:333)
[error]     at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401) [error] at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:396) [error] at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:475) [error] at org.scalatest.flatspec.AnyFlatSpecLike.runTests(AnyFlatSpecLike.scala:1751) [error] at org.scalatest.flatspec.AnyFlatSpecLike.runTests$(AnyFlatSpecLike.scala:1750)
[error]     at org.scalatest.flatspec.AnyFlatSpec.runTests(AnyFlatSpec.scala:1685)
[error]     at org.scalatest.Suite.run(Suite.scala:1112)
[error]     at org.scalatest.Suite.run$(Suite.scala:1094) [error] at org.scalatest.flatspec.AnyFlatSpec.org$scalatest$flatspec$AnyFlatSpecLike$$super$run(AnyFlatSpec.scala:1685)
[error]     at org.scalatest.flatspec.AnyFlatSpecLike.$anonfun$run$1(AnyFlatSpecLike.scala:1796) [error] at org.scalatest.SuperEngine.runImpl(Engine.scala:535) [error] at org.scalatest.flatspec.AnyFlatSpecLike.run(AnyFlatSpecLike.scala:1796) [error] at org.scalatest.flatspec.AnyFlatSpecLike.run$(AnyFlatSpecLike.scala:1794)
[error]     at org.scalatest.flatspec.AnyFlatSpec.run(AnyFlatSpec.scala:1685)
[error]     at org.scalatest.tools.Framework.org$scalatest$tools$Framework$$runSuite(Framework.scala:318)
[error]     at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:513) [error] at sbt.TestRunner.runTest$1(TestFramework.scala:139)
[error]     at sbt.TestRunner.run(TestFramework.scala:154)
[error]     at sbt.TestFramework$$anon$3$$anonfun$$lessinit$greater$1.$anonfun$apply$1(TestFramework.scala:317) [error] at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:277)
[error]     at sbt.TestFramework$$anon$3$$anonfun$$lessinit$greater$1.apply(TestFramework.scala:317)
[error]     at sbt.TestFramework$$anon$3$$anonfun$$lessinit$greater$1.apply(TestFramework.scala:317)
[error]     at sbt.TestFunction.apply(TestFramework.scala:329)
[error]     at sbt.Tests$.$anonfun$toTask$1(Tests.scala:311)
[error]     at sbt.std.Transform$$anon$3.$anonfun$apply$2(Transform.scala:46) [error] at sbt.std.Transform$$anon$4.work(Transform.scala:67) [error] at sbt.Execute.$anonfun$submit$2(Execute.scala:281)
[error]     at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:19) [error] at sbt.Execute.work(Execute.scala:290) [error] at sbt.Execute.$anonfun$submit$1(Execute.scala:281)
[error]     at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178) [error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:37) [error] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [error] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error]     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error]     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [error] at java.lang.Thread.run(Thread.java:748) [error] (Test / executeTests) java.lang.NoSuchFieldError: App$ArrayDefs$IsArrSyntax$IsArrOps$$tc1d

Entonces, el problema parece ser cómo IntelliJ y sbt ejecutan Scalatest.

NoSuchFieldError Java

Java NoSuchFieldError cuando se usa Reflection

https://github.com/unicredit/hbase-rdd/issues/21