From c5117700bed47d6e9d8a83c3b0cc0a8b1531b14c Mon Sep 17 00:00:00 2001 From: Gabor Roczei <1918366+roczei@users.noreply.github.com> Date: Thu, 1 Oct 2026 10:12:24 +0200 Subject: [PATCH] [LIVY-1089] Upgrade Mockito 1.10.19 -> 3.4.6 (mockito-all -> mockito-core) ## What changes were proposed in this pull request? mockito-all:1.10.19 is an uber-jar that bundles Hamcrest 1.x which conflicts with the Hamcrest 2.x pulled in by the ScalaTest 3.2.9 / scalatestplus mockito-3-4 upgrade: the bundled LocalizedMatcher does not implement Matcher.describeMismatch(Object, Description) and fails to compile. This switches to mockito-core (which does not bundle Hamcrest) and aligns the version with the mockito-3-4_2.13:3.2.9.0 binding. - pom.xml: mockito-all -> mockito-core, version 1.10.19 -> 3.4.6 - Replace removed org.mockito.Matchers with org.mockito.ArgumentMatchers - Replace removed anyObject() with any() - Rewrite the custom ArgumentMatcher[Path] to the Mockito 2+ shape (matches(T) instead of matches(Object); drop the removed describeTo), dropping the now-unused Hamcrest Description and internal Equals imports Note: in Mockito 3.4.6 org.mockito.Matchers still exists only as a deprecated subclass of ArgumentMatchers and declares no members of its own, so Scala cannot import its inherited statics (e.g. "import org.mockito.Matchers.any" fails to compile). All Scala specs must import from org.mockito.ArgumentMatchers directly. Updated specs: HttpClientSpec, ScalaJobHandleTest, BatchSessionSpec, InteractiveSessionServletSpec, InteractiveSessionSpec, FileSystemStateStoreSpec, SparkYarnAppSpec. JIRA: https://issues.apache.org/jira/browse/LIVY-1089 ## How was this patch tested? Compiled the server module and its reactor dependencies with `mvn -pl server -am test-compile`, which succeeds (exit 0) and confirms all migrated specs now compile under Mockito 3.4.6 - including SparkYarnAppSpec, whose `import org.mockito.Matchers.any` would otherwise fail to compile. Also compiled the thriftserver modules with the profile enabled via `mvn -Pthriftserver -pl thriftserver/server,thriftserver/session,thriftserver/client -am test-compile`, which succeeds (exit 0) - its tests use org.mockito.Mockito mock/when, which are unaffected by the migration. Existing unit tests exercise the migrated mocks. ## Was this patch authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 4.8) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../org/apache/livy/client/http/HttpClientSpec.scala | 2 +- pom.xml | 4 ++-- .../org/apache/livy/scalaapi/ScalaJobHandleTest.scala | 2 +- .../apache/livy/server/batch/BatchSessionSpec.scala | 8 ++++---- .../interactive/InteractiveSessionServletSpec.scala | 2 +- .../server/interactive/InteractiveSessionSpec.scala | 10 +++++----- .../server/recovery/FileSystemStateStoreSpec.scala | 10 ++-------- .../scala/org/apache/livy/utils/SparkYarnAppSpec.scala | 2 +- 8 files changed, 17 insertions(+), 23 deletions(-) diff --git a/client-http/src/test/scala/org/apache/livy/client/http/HttpClientSpec.scala b/client-http/src/test/scala/org/apache/livy/client/http/HttpClientSpec.scala index 54ab56419..6bcb008b5 100644 --- a/client-http/src/test/scala/org/apache/livy/client/http/HttpClientSpec.scala +++ b/client-http/src/test/scala/org/apache/livy/client/http/HttpClientSpec.scala @@ -28,7 +28,7 @@ import javax.servlet.http.HttpServletRequest import scala.concurrent.{ExecutionContext, Future} import org.mockito.ArgumentCaptor -import org.mockito.Matchers.{eq => meq, _} +import org.mockito.ArgumentMatchers.{eq => meq, _} import org.mockito.Mockito._ import org.scalatest.BeforeAndAfterAll import org.scalatest.funspec.AnyFunSpecLike diff --git a/pom.xml b/pom.xml index b54b8e69f..8c6f75180 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ and metrics-healthchecks on 3.1.0 causes a NoClassDefFoundError for HealthCheckFilter at runtime (the class moved in Dropwizard 4.x). --> 4.2.19 - 1.10.19 + 3.4.6 @@ -265,7 +265,7 @@ org.mockito - mockito-all + mockito-core ${mockito.version} test diff --git a/scala-api/src/test/scala/org/apache/livy/scalaapi/ScalaJobHandleTest.scala b/scala-api/src/test/scala/org/apache/livy/scalaapi/ScalaJobHandleTest.scala index d82282d63..a97d74c0f 100644 --- a/scala-api/src/test/scala/org/apache/livy/scalaapi/ScalaJobHandleTest.scala +++ b/scala-api/src/test/scala/org/apache/livy/scalaapi/ScalaJobHandleTest.scala @@ -24,7 +24,7 @@ import scala.concurrent.ExecutionContext.Implicits.global import scala.language.postfixOps import scala.util.{Failure, Success} -import org.mockito.Matchers._ +import org.mockito.ArgumentMatchers._ import org.mockito.Mockito._ import org.scalatest.BeforeAndAfter import org.scalatest.concurrent.ScalaFutures diff --git a/server/src/test/scala/org/apache/livy/server/batch/BatchSessionSpec.scala b/server/src/test/scala/org/apache/livy/server/batch/BatchSessionSpec.scala index 57bfed3a1..e9734b22e 100644 --- a/server/src/test/scala/org/apache/livy/server/batch/BatchSessionSpec.scala +++ b/server/src/test/scala/org/apache/livy/server/batch/BatchSessionSpec.scala @@ -23,8 +23,8 @@ import java.util.concurrent.TimeUnit import scala.concurrent.duration.Duration -import org.mockito.Matchers -import org.mockito.Matchers.anyObject +import org.mockito.ArgumentMatchers +import org.mockito.ArgumentMatchers.any import org.mockito.Mockito._ import org.scalatest.BeforeAndAfter import org.scalatest.funspec.AnyFunSpec @@ -112,7 +112,7 @@ class BatchSessionSpec val expectedAppId = "APPID" batch.appIdKnown(expectedAppId) verify(sessionStore, atLeastOnce()).save( - Matchers.eq(BatchSession.RECOVERY_SESSION_TYPE), anyObject()) + ArgumentMatchers.eq(BatchSession.RECOVERY_SESSION_TYPE), any()) batch.appId shouldEqual Some(expectedAppId) val expectedAppInfo = AppInfo(Some("DRIVER LOG URL"), Some("SPARK UI URL")) @@ -207,7 +207,7 @@ class BatchSessionSpec batch.appIdKnown("appId") verify(sessionStore, atLeastOnce()).save( - Matchers.eq(BatchSession.RECOVERY_SESSION_TYPE), anyObject()) + ArgumentMatchers.eq(BatchSession.RECOVERY_SESSION_TYPE), any()) } Seq[Option[String]](None, Some("Test Batch Session"), null) diff --git a/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionServletSpec.scala b/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionServletSpec.scala index 50360b053..01c6b96d4 100644 --- a/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionServletSpec.scala +++ b/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionServletSpec.scala @@ -26,7 +26,7 @@ import scala.concurrent.Future import scala.language.postfixOps import org.json4s.jackson.Json4sScalaModule -import org.mockito.Matchers._ +import org.mockito.ArgumentMatchers._ import org.mockito.Mockito.when import org.mockito.invocation.InvocationOnMock import org.mockito.stubbing.Answer diff --git a/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionSpec.scala b/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionSpec.scala index 7bdaf0156..592bc194a 100644 --- a/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionSpec.scala +++ b/server/src/test/scala/org/apache/livy/server/interactive/InteractiveSessionSpec.scala @@ -26,8 +26,8 @@ import scala.language.postfixOps import org.apache.spark.launcher.SparkLauncher import org.json4s.{DefaultFormats, Extraction, JValue} import org.json4s.jackson.JsonMethods.parse -import org.mockito.{Matchers => MockitoMatchers} -import org.mockito.Matchers._ +import org.mockito.{ArgumentMatchers => MockitoMatchers} +import org.mockito.ArgumentMatchers._ import org.mockito.Mockito.{atLeastOnce, verify, when} import org.scalatest.BeforeAndAfterAll import org.scalatest.concurrent.Eventually._ @@ -178,7 +178,7 @@ class InteractiveSessionSpec extends AnyFunSpec session.appInfo shouldEqual expectedAppInfo verify(sessionStore, atLeastOnce()).save( - MockitoMatchers.eq(InteractiveSession.RECOVERY_SESSION_TYPE), anyObject()) + MockitoMatchers.eq(InteractiveSession.RECOVERY_SESSION_TYPE), any()) session.state should (be(SessionState.Starting) or be(SessionState.Idle)) } @@ -299,7 +299,7 @@ class InteractiveSessionSpec extends AnyFunSpec s.appIdKnown("appId") verify(sessionStore, atLeastOnce()).save( - MockitoMatchers.eq(InteractiveSession.RECOVERY_SESSION_TYPE), anyObject()) + MockitoMatchers.eq(InteractiveSession.RECOVERY_SESSION_TYPE), any()) } it("should recover sessions with no name") { @@ -318,7 +318,7 @@ class InteractiveSessionSpec extends AnyFunSpec s.appIdKnown("appId") verify(sessionStore, atLeastOnce()).save( - MockitoMatchers.eq(InteractiveSession.RECOVERY_SESSION_TYPE), anyObject()) + MockitoMatchers.eq(InteractiveSession.RECOVERY_SESSION_TYPE), any()) } it("should recover session to dead state if rscDriverUri is unknown") { diff --git a/server/src/test/scala/org/apache/livy/server/recovery/FileSystemStateStoreSpec.scala b/server/src/test/scala/org/apache/livy/server/recovery/FileSystemStateStoreSpec.scala index cbedb1e6e..f5d56c8c8 100644 --- a/server/src/test/scala/org/apache/livy/server/recovery/FileSystemStateStoreSpec.scala +++ b/server/src/test/scala/org/apache/livy/server/recovery/FileSystemStateStoreSpec.scala @@ -24,11 +24,9 @@ import org.apache.hadoop.fs._ import org.apache.hadoop.fs.Options.{CreateOpts, Rename} import org.apache.hadoop.fs.permission.FsPermission import org.apache.hadoop.hdfs.DistributedFileSystem -import org.hamcrest.Description import org.mockito.ArgumentMatcher -import org.mockito.Matchers.{any, anyInt, argThat, eq => equal} +import org.mockito.ArgumentMatchers.{any, anyInt, argThat, eq => equal} import org.mockito.Mockito.{atLeastOnce, spy, verify, when} -import org.mockito.internal.matchers.Equals import org.mockito.invocation.InvocationOnMock import org.mockito.stubbing.Answer import org.scalatest.funspec.AnyFunSpec @@ -40,11 +38,7 @@ import org.apache.livy.{LivyBaseUnitTestSuite, LivyConf} class FileSystemStateStoreSpec extends AnyFunSpec with LivyBaseUnitTestSuite { describe("FileSystemStateStore") { def pathEq(wantedPath: String): Path = argThat(new ArgumentMatcher[Path] { - private val matcher = new Equals(wantedPath) - - override def matches(path: Any): Boolean = matcher.matches(path.toString) - - override def describeTo(d: Description): Unit = { matcher.describeTo(d) } + override def matches(path: Path): Boolean = path.toString == wantedPath }) def makeConf(): LivyConf = { diff --git a/server/src/test/scala/org/apache/livy/utils/SparkYarnAppSpec.scala b/server/src/test/scala/org/apache/livy/utils/SparkYarnAppSpec.scala index ab2f5167d..c6b3ad0df 100644 --- a/server/src/test/scala/org/apache/livy/utils/SparkYarnAppSpec.scala +++ b/server/src/test/scala/org/apache/livy/utils/SparkYarnAppSpec.scala @@ -31,7 +31,7 @@ import org.apache.hadoop.yarn.client.api.YarnClient import org.apache.hadoop.yarn.exceptions.ApplicationAttemptNotFoundException import org.apache.hadoop.yarn.util.ConverterUtils import org.mockito.ArgumentCaptor -import org.mockito.Matchers.any +import org.mockito.ArgumentMatchers.any import org.mockito.Mockito._ import org.mockito.invocation.InvocationOnMock import org.mockito.stubbing.Answer