December 28, 2024
Add the following to your build.sbt file to resolve the dynamic loading Java agent warning:
val mockitoVersion = "5.14.2" Test / fork := true, Test / javaOptions := Seq( s"-javaagent:${csrCacheDirectory.value.getAbsolutePath()}/https/repo1.maven.org/maven2/org/ mockito/mockito-core/${mockitoVersion}/mockito-core-${mockitoVersion}.jar", ),
If you are using Mockito in your Scala tests (not mockito-scala) and you are on a recent JVM version (>= 21), you may have seen the following warning:
Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build what is described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0.3 WARNING: A Java agent has been loaded dynamically (/Users/username/Library/Caches/Coursier/ v1/https/repo1.maven.org/maven2/net/bytebuddy/byte-buddy-agent/1.15.4/byte-buddy-agent-1.15.4.jar) WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information WARNING: Dynamic loading of agents will be disallowed by default in a future release
To fix this warning, you need to set the javaOptions for the test JVM in the Scala build.sbt file. You need to find where the Mockito jar file is located on your system. Use the byte-buddy-agent path in the warning message as a hint for where Mockito is probably located. This is the path mentioned in the warning:
/Users/username/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/net/bytebuddy/ byte-buddy-agent/1.15.4/byte-buddy-agent-1.15.4.jar
In the maven2 directory, Mockito should be located at the path org/mockito/mockito-core/<version> which will match the dependency entry in your build.sbt file ("org.mockito" % "mockito-core" % "5.14.2"). For my system (macOS and SBT), the Mockito jar is located at:
/Users/username/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/ mockito/mockito-core/5.14.2/mockito-core-5.14.2.jar
Open the build.sbt file for your Scala project and add the following to your Test configuration:
Test / javaOptions := Seq( "-javaagent:/Users/username/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/ org/mockito/mockito-core/5.14.2/mockito-core-5.14.2.jar", ),
You will also need to add Test / fork := true to your build.sbt file. The result should look something like this:
lazy val root = project .in(file(".")) .settings( // Omitted all project settings for brevity. libraryDependencies ++= Seq( "org.mockito" % "mockito-core" % "5.14.2" % Test, ), Test / javaOptions := Seq( "-javaagent:/Users/username/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/ org/mockito/mockito-core/5.14.2/mockito-core-5.14.2.jar", ), Test / fork := true, )
In your SBT shell, reload the project, and re-run your tests. The warning message should no longer be visible. Woo hoo!!
Let's update the path so it's not hardcoded to a specific Mockito version. In your build.sbt file, create a value for the Mockito version number (val mockitoVersion = "5.14.2") and use the value in your dependencies:
"org.mockito" % "mockito-core" % mockitoVersion % Test,
Modify the javaOptions string to be an interpolated string (notice the "s" at the beginning), and add the Mockito version there too:
Test / javaOptions := Seq( s"-javaagent:/Users/username/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/ org/mockito/mockito-core/${mockitoVersion}/mockito-core-${mockitoVersion}.jar", ),
Let's also update the cache path to work for various operating systems, so it's not hardcoded to your system. To get the cache path we need to know which SBT key the value is stored under — it's helpful to know that SBT uses Coursier for managed dependencies, and the key is csrCacheDirectory. In the SBT shell, enter show csrCacheDirectory to see the path value:
/Users/username/Library/Caches/Coursier/v1
You may recognize that path as part of the path you discovered earlier. To get the absolute path from this, you will use csrCacheDirectory.value.getAbsolutePath() in your java options string. Your final build.sbt file should look similar to this with all the changes you've made:
val mockitoVersion = "5.14.2" lazy val root = project .in(file(".")) .settings( // Omitted all project settings for brevity. libraryDependencies ++= Seq( "org.mockito" % "mockito-core" % mockitoVersion % Test, ), Test / javaOptions := Seq( s"-javaagent:${csrCacheDirectory.value.getAbsolutePath()}/https/repo1.maven.org/maven2/org/ mockito/mockito-core/${mockitoVersion}/mockito-core-${mockitoVersion}.jar", ), Test / fork := true, )
I hope you found this post helpful, and it resolved the dynamic Java agent warning message. If you have any questions, please reach out to me.
The following dependencies were used in this post.