mockito/mockito-scala

jdk21: use latest mockito-core as dependency for updated bytebuddy

domdorn opened this issue · 5 comments

My project only had included mockito-scala as dependency.
When upgrading to JDK21, we've got the following error:

[info]   org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: interface zio.ZIO.
[info]
[info] If you're not sure why you're getting this error, please open an issue on GitHub.
[info]
[info]
[info] Java               : 21
[info] JVM vendor name    : Oracle Corporation
[info] JVM vendor version : 21.0.1+12-jvmci-23.1-b19
[info] JVM name           : Java HotSpot(TM) 64-Bit Server VM
[info] JVM version        : 21.0.1+12-jvmci-23.1-b19
[info] JVM info           : mixed mode, sharing
[info] OS name            : Mac OS X
[info] OS version         : 13.3.1
[info]
[info]
[info] You are seeing this disclaimer because Mockito is configured to create inlined mocks.
[info] You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.
[info]
[info] Underlying exception : org.mockito.exceptions.base.MockitoException: Could not modify all classes [interface scala.Product, interface java.io.Serializable, interface zio.ZIOPlatformSpecific, interface zio.ZIOVersionSpecific, interface zio.ZIO, interface scala.Equals]
[info]   at scala.Option.orElse(Option.scala:477)
[info]   at com.acme.xxx.masterdata.plots.services.getcalculationparameters.impl.GetCalculationParametersServiceSpec.$anonfun$new$2(GetCalculationParametersServiceSpec.scala:98)
[info]   at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
[info]   at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
[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.wordspec.AnyWordSpecLike$$anon$3.apply(AnyWordSpecLike.scala:1240)
[info]   at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
[info]   at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)

our Dependencies.scala looks like this

    val mockitoScalaVersion       = "1.17.29"
    val mockitoCoreVersion        = "5.7.0"

    object Mockito {
      val core           = "org.mockito" % "mockito-core" % V.mockitoCoreVersion
      val scala          = "org.mockito" %% "mockito-scala"           % V.mockitoScalaVersion
      val scalaScalatest = "org.mockito" %% "mockito-scala-scalatest" % V.mockitoScalaVersion
      val scalaCats      = "org.mockito" %% "mockito-scala-cats"      % V.mockitoScalaVersion

    }

Without the explicit inclusion of mockito-core an old version of mockito was pulled in which included a bytebuddy version that does not yet understand JDK21 classes.

Do you mind sending us a PR that upgrades to Mockito 5 and resolves the deprecations? Then I can publish a new release for it.

Just tried to make a PR but running into a few problems:

1.) .sbtOpts contains

--J-XX:+CMSClassUnloadingEnabled

which does not work on jdk21, is this necessary for something?

2.) building the compiler bridge with scala 2.13.8 does not work with jdk21 .. I upgraded to scala 2.13.12

3.) there are quite a few tests failing, all related to reflection

[error] 	user.org.mockito.PrefixExpectationsTest
[error] 	user.org.mockito.IdiomaticStubbingTest
[error] 	user.org.mockito.Issue352
[error] 	user.org.mockito.MockitoScalaSessionTest
[error] 	user.org.mockito.MockitoSugarTest
[error] 	user.org.mockito.PostfixVerificationsTest

with errors like this:

[info] - should object stubbing should be thread safe 2 *** FAILED ***
[info]   java.lang.NoSuchFieldException: modifiers
[info]   at java.base/java.lang.Class.getDeclaredField(Class.java:2782)
[info]   at org.mockito.ReflectionUtils$.$anonfun$setFinalStatic$1(ReflectionUtils.scala:130)
[info]   at scala.util.Try$.apply(Try.scala:210)
[info]   at org.mockito.ReflectionUtils$.setFinalStatic(ReflectionUtils.scala:130)
[info]   at org.mockito.MockitoEnhancer.withObject(MockitoAPI.scala:631)
[info]   at org.mockito.MockitoEnhancer.withObject$(MockitoAPI.scala:620)
[info]   at user.org.mockito.IdiomaticStubbingTest.withObject(IdiomaticStubbingTest.scala:14)
[info]   at org.mockito.MockitoEnhancer.withObjectMocked(MockitoAPI.scala:607)
[info]   at org.mockito.MockitoEnhancer.withObjectMocked$(MockitoAPI.scala:606)
[info]   at user.org.mockito.IdiomaticStubbingTest.withObjectMocked(IdiomaticStubbingTest.scala:14)

4.) some code is not compiling/logging errors

[error] /Users/domdorn/work/mockito-scala/specs2/src/test/scala/org/mockito/specs2/MockitoScalaNewSyntaxSpec.scala:664:22: Implicit definition should have explicit type (inferred org.mockito.VerifyInOrder) [quickfixable]
[error]         implicit val order = inOrder(list1, list2)
[error]                      ^
[error] /Users/domdorn/work/mockito-scala/specs2/src/test/scala/org/mockito/specs2/MockitoScalaSpec.scala:663:22: Implicit definition should have explicit type (inferred org.mockito.VerifyInOrder) [quickfixable]
[error]         implicit val order = inOrder(list1, list2)
[error]                      ^
[error] two errors found

Are there requirements for building on jdk < 21 or scala < 2.13 < 12 ?

Based on https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html it appears we need to upgrade Scala to 2.13.11 and SBT to 1.9.0 minimum. Let's do the upgrade to SBT first and then we do Scala?

@domdorn I think +CMSClassUnloadingEnabled should be removed. This setting is only valid when using the Concurrent Mark Sweep garbage collector. This garbage collector has to be explicitly enabled with -XX:+UseConcMarkSweepGC. I'm a bit confused how the option even ended up in the config, as no explict garbage collector seems to have been configured. The default in Java 8 is Parallel GC. (Having said that, I'm only a random guy from the Internet who just had a quick glance at the repo 😅).

I'm wondering what the plan is anyway for building with JVM versions in the CI workflow. Currently, the project is built with versions 8, 11 and 14. Should new versions be added? Only LTS versions or more?

@TimvdLippe Are you maintaining the project? Would be great if this was documented in the README. It currently only lists Bruno Bonnano as the author, who apparently does not exist any more. 🤔

@ultrasecreth was maintainer in their spare time. I sometimes click the merge button on automated PRs. Feel free to submit a PR and then we can take a look.