From 10a55ddd1d6eaf19686992a55f1e1c2d05fb53ab Mon Sep 17 00:00:00 2001 From: Bruno Bonanno <241804+bbonanno@users.noreply.github.com> Date: Wed, 1 Aug 2018 18:00:01 +0100 Subject: [PATCH 1/7] Multi module project to hold macros --- build.sbt | 84 ++++++++++++++----- .../java/org/mockito/MockitoEnhancerUtil.java | 0 .../org/mockito/ArgumentMatchersSugar.scala | 0 .../main/scala/org/mockito/MockitoSugar.scala | 0 .../scala/org/mockito/ReflectionUtils.scala | 0 .../org/mockito/matchers/AnyMatchers.scala | 0 .../org/mockito/matchers/EqMatchers.scala | 0 .../org/mockito/matchers/NullMatchers.scala | 0 .../mockito/matchers/StringThatMatchers.scala | 0 .../org/mockito/matchers/ThatMatchers.scala | 0 .../scala/org/mockito/DoSomethingTest.scala | 0 .../scala/org/mockito/MockitoSugarTest.scala | 0 .../mockito/matchers/AnyMatchersTest.scala | 0 .../org/mockito/matchers/EqMatchersTest.scala | 0 .../mockito/matchers/ThatMatchersTest.scala | 0 15 files changed, 61 insertions(+), 23 deletions(-) rename {src => core/src}/main/java/org/mockito/MockitoEnhancerUtil.java (100%) rename {src => core/src}/main/scala/org/mockito/ArgumentMatchersSugar.scala (100%) rename {src => core/src}/main/scala/org/mockito/MockitoSugar.scala (100%) rename {src => core/src}/main/scala/org/mockito/ReflectionUtils.scala (100%) rename {src => core/src}/main/scala/org/mockito/matchers/AnyMatchers.scala (100%) rename {src => core/src}/main/scala/org/mockito/matchers/EqMatchers.scala (100%) rename {src => core/src}/main/scala/org/mockito/matchers/NullMatchers.scala (100%) rename {src => core/src}/main/scala/org/mockito/matchers/StringThatMatchers.scala (100%) rename {src => core/src}/main/scala/org/mockito/matchers/ThatMatchers.scala (100%) rename {src => core/src}/test/scala/org/mockito/DoSomethingTest.scala (100%) rename {src => core/src}/test/scala/org/mockito/MockitoSugarTest.scala (100%) rename {src => core/src}/test/scala/org/mockito/matchers/AnyMatchersTest.scala (100%) rename {src => core/src}/test/scala/org/mockito/matchers/EqMatchersTest.scala (100%) rename {src => core/src}/test/scala/org/mockito/matchers/ThatMatchersTest.scala (100%) diff --git a/build.sbt b/build.sbt index ead67606..5a47fe3a 100644 --- a/build.sbt +++ b/build.sbt @@ -1,31 +1,69 @@ +import sbt.Keys._ + import scala.io.Source import scala.language.postfixOps import scala.util.Try -name := "mockito-scala" -organization := "org.mockito" - -licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT")) -homepage := Some(url("https://github.com/mockito/mockito-scala")) -scmInfo := Some(ScmInfo(url("https://github.com/mockito/mockito-scala"), "git@github.com:mockito/mockito-scala.git")) -developers := List( - Developer("bbonanno", "Bruno Bonanno", "bbonanno@gmail.com", url("https://github.com/bbonanno")) -) +lazy val commonSettings = + Seq( + scalaVersion := "2.12.6", + organization := "org.mockito", + //Load version from the file so that Gradle/Shipkit and SBT use the same version + version := { + val pattern = """^version=(.+)$""".r + val source = Source.fromFile("version.properties") + val version = Try(source.getLines.collectFirst { + case pattern(v) => v + }.get) + source.close + version.get + } + ) -//Load version from the file so that Gradle/Shipkit and SBT use the same version -version := { - val pattern = """^version=(.+)$""".r - val source = Source.fromFile("version.properties") - val version = Try(source.getLines.collectFirst { - case pattern(v) => v - }.get) - source.close - version.get +lazy val scalaReflect = Def.setting { + "org.scala-lang" % "scala-reflect" % scalaVersion.value } -scalaVersion := "2.12.6" - -libraryDependencies += "org.mockito" % "mockito-core" % "2.19.0" -libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.12.6" +lazy val core = (project in file("core")) + .dependsOn(macroSub % "compile-internal, test-internal") + .settings( + commonSettings, + name := "mockito-scala", + libraryDependencies ++= Seq( + "org.mockito" % "mockito-core" % "2.19.0", + scalaReflect.value, + "org.scalatest" %% "scalatest" % "3.0.5" % Test + ), + // include the macro classes and resources in the main jar + mappings in (Compile, packageBin) ++= mappings + .in(macroSub, Compile, packageBin) + .value, + // include the macro sources in the main source jar + mappings in (Compile, packageSrc) ++= mappings + .in(macroSub, Compile, packageSrc) + .value, + licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT")), + homepage := Some(url("https://github.com/mockito/mockito-scala")), + scmInfo := Some( + ScmInfo( + url("https://github.com/mockito/mockito-scala"), + "git@github.com:mockito/mockito-scala.git" + ) + ), + developers := List( + Developer( + "bbonanno", + "Bruno Bonanno", + "bbonanno@gmail.com", + url("https://github.com/bbonanno") + ) + ) + ) -libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % Test +lazy val macroSub = (project in file("macro")) + .settings( + commonSettings, + libraryDependencies += scalaReflect.value, + publish := {}, + publishLocal := {} + ) diff --git a/src/main/java/org/mockito/MockitoEnhancerUtil.java b/core/src/main/java/org/mockito/MockitoEnhancerUtil.java similarity index 100% rename from src/main/java/org/mockito/MockitoEnhancerUtil.java rename to core/src/main/java/org/mockito/MockitoEnhancerUtil.java diff --git a/src/main/scala/org/mockito/ArgumentMatchersSugar.scala b/core/src/main/scala/org/mockito/ArgumentMatchersSugar.scala similarity index 100% rename from src/main/scala/org/mockito/ArgumentMatchersSugar.scala rename to core/src/main/scala/org/mockito/ArgumentMatchersSugar.scala diff --git a/src/main/scala/org/mockito/MockitoSugar.scala b/core/src/main/scala/org/mockito/MockitoSugar.scala similarity index 100% rename from src/main/scala/org/mockito/MockitoSugar.scala rename to core/src/main/scala/org/mockito/MockitoSugar.scala diff --git a/src/main/scala/org/mockito/ReflectionUtils.scala b/core/src/main/scala/org/mockito/ReflectionUtils.scala similarity index 100% rename from src/main/scala/org/mockito/ReflectionUtils.scala rename to core/src/main/scala/org/mockito/ReflectionUtils.scala diff --git a/src/main/scala/org/mockito/matchers/AnyMatchers.scala b/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala similarity index 100% rename from src/main/scala/org/mockito/matchers/AnyMatchers.scala rename to core/src/main/scala/org/mockito/matchers/AnyMatchers.scala diff --git a/src/main/scala/org/mockito/matchers/EqMatchers.scala b/core/src/main/scala/org/mockito/matchers/EqMatchers.scala similarity index 100% rename from src/main/scala/org/mockito/matchers/EqMatchers.scala rename to core/src/main/scala/org/mockito/matchers/EqMatchers.scala diff --git a/src/main/scala/org/mockito/matchers/NullMatchers.scala b/core/src/main/scala/org/mockito/matchers/NullMatchers.scala similarity index 100% rename from src/main/scala/org/mockito/matchers/NullMatchers.scala rename to core/src/main/scala/org/mockito/matchers/NullMatchers.scala diff --git a/src/main/scala/org/mockito/matchers/StringThatMatchers.scala b/core/src/main/scala/org/mockito/matchers/StringThatMatchers.scala similarity index 100% rename from src/main/scala/org/mockito/matchers/StringThatMatchers.scala rename to core/src/main/scala/org/mockito/matchers/StringThatMatchers.scala diff --git a/src/main/scala/org/mockito/matchers/ThatMatchers.scala b/core/src/main/scala/org/mockito/matchers/ThatMatchers.scala similarity index 100% rename from src/main/scala/org/mockito/matchers/ThatMatchers.scala rename to core/src/main/scala/org/mockito/matchers/ThatMatchers.scala diff --git a/src/test/scala/org/mockito/DoSomethingTest.scala b/core/src/test/scala/org/mockito/DoSomethingTest.scala similarity index 100% rename from src/test/scala/org/mockito/DoSomethingTest.scala rename to core/src/test/scala/org/mockito/DoSomethingTest.scala diff --git a/src/test/scala/org/mockito/MockitoSugarTest.scala b/core/src/test/scala/org/mockito/MockitoSugarTest.scala similarity index 100% rename from src/test/scala/org/mockito/MockitoSugarTest.scala rename to core/src/test/scala/org/mockito/MockitoSugarTest.scala diff --git a/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala similarity index 100% rename from src/test/scala/org/mockito/matchers/AnyMatchersTest.scala rename to core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala diff --git a/src/test/scala/org/mockito/matchers/EqMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala similarity index 100% rename from src/test/scala/org/mockito/matchers/EqMatchersTest.scala rename to core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala diff --git a/src/test/scala/org/mockito/matchers/ThatMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/ThatMatchersTest.scala similarity index 100% rename from src/test/scala/org/mockito/matchers/ThatMatchersTest.scala rename to core/src/test/scala/org/mockito/matchers/ThatMatchersTest.scala From 11361f93257e96256d52858b293928488663c1e7 Mon Sep 17 00:00:00 2001 From: Bruno Bonanno <241804+bbonanno@users.noreply.github.com> Date: Wed, 1 Aug 2018 18:13:00 +0100 Subject: [PATCH 2/7] Apply new formatting --- .scalafmt.conf | 8 + .travis.yml | 6 +- build.sbt | 2 +- .../java/org/mockito/MockitoEnhancerUtil.java | 6 +- .../org/mockito/ArgumentMatchersSugar.scala | 33 +- .../main/scala/org/mockito/MockitoSugar.scala | 342 +++++++++--------- .../scala/org/mockito/ReflectionUtils.scala | 7 +- .../org/mockito/matchers/AnyMatchers.scala | 217 +++++------ .../org/mockito/matchers/EqMatchers.scala | 59 +-- .../org/mockito/matchers/NullMatchers.scala | 35 +- .../mockito/matchers/StringThatMatchers.scala | 51 +-- .../org/mockito/matchers/ThatMatchers.scala | 126 +++---- .../scala/org/mockito/DoSomethingTest.scala | 182 +++++----- .../scala/org/mockito/MockitoSugarTest.scala | 51 ++- .../mockito/matchers/AnyMatchersTest.scala | 191 +++++----- .../org/mockito/matchers/EqMatchersTest.scala | 180 +++++---- .../mockito/matchers/ThatMatchersTest.scala | 139 ++++--- gradle/shipkit.gradle | 8 +- project/build.properties | 2 +- 19 files changed, 851 insertions(+), 794 deletions(-) create mode 100644 .scalafmt.conf diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 00000000..9c9a9568 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,8 @@ +style = defaultWithAlign + +docstrings = JavaDoc +maxColumn = 120 +rewrite.rules = [RedundantBraces, RedundantParens, SortImports] +spaces.inImportCurlyBraces = true +indentOperator = spray +unindentTopLevelOperators = true diff --git a/.travis.yml b/.travis.yml index 2ba2f178..39a171a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,12 @@ language: java jdk: - - oraclejdk8 +- oraclejdk8 #Skipping install step to avoid having Travis run arbitrary './gradlew assemble' task # https://docs.travis-ci.com/user/customizing-the-build/#Skipping-the-Installation-Step install: - - true +- true #Don't build tags branches: @@ -18,4 +18,4 @@ branches: #Build and perform release (if needed) script: - - ./gradlew build -s && ./gradlew ciPerformRelease +- ./gradlew build -s && ./gradlew ciPerformRelease diff --git a/build.sbt b/build.sbt index 5a47fe3a..f3e0fea4 100644 --- a/build.sbt +++ b/build.sbt @@ -11,7 +11,7 @@ lazy val commonSettings = //Load version from the file so that Gradle/Shipkit and SBT use the same version version := { val pattern = """^version=(.+)$""".r - val source = Source.fromFile("version.properties") + val source = Source.fromFile("version.properties") val version = Try(source.getLines.collectFirst { case pattern(v) => v }.get) diff --git a/core/src/main/java/org/mockito/MockitoEnhancerUtil.java b/core/src/main/java/org/mockito/MockitoEnhancerUtil.java index 5510137c..04848a39 100644 --- a/core/src/main/java/org/mockito/MockitoEnhancerUtil.java +++ b/core/src/main/java/org/mockito/MockitoEnhancerUtil.java @@ -32,9 +32,9 @@ class MockitoEnhancerUtil { static T stubMock(T aMock) { Stream.of(aMock.getClass().getMethods()) - .filter(m -> !isStatic(m.getModifiers())) - .filter(m -> m.getName().contains("$default$")) - .forEach(defaultParamMethod -> when(call(defaultParamMethod, aMock)).thenCallRealMethod()); + .filter(m -> !isStatic(m.getModifiers())) + .filter(m -> m.getName().contains("$default$")) + .forEach(defaultParamMethod -> when(call(defaultParamMethod, aMock)).thenCallRealMethod()); return aMock; } diff --git a/core/src/main/scala/org/mockito/ArgumentMatchersSugar.scala b/core/src/main/scala/org/mockito/ArgumentMatchersSugar.scala index 9136ed30..3de51e51 100644 --- a/core/src/main/scala/org/mockito/ArgumentMatchersSugar.scala +++ b/core/src/main/scala/org/mockito/ArgumentMatchersSugar.scala @@ -14,20 +14,25 @@ package org.mockito import org.mockito.matchers._ /** - * Trait that provides some syntax sugar and type mapping. - * - * It mostly forwards the calls to org.mockito.ArgumentMatchers, but with a few improvements to make it more scala-like - * It also renames the "eq" matcher to "eqTo" as in Scala "eq" is a keyword used to do object identity equality - * - * @author Bruno Bonanno - * - */ -trait ArgumentMatchersSugar extends AnyMatchers with EqMatchers with ThatMatchers with StringThatMatchers with NullMatchers + * Trait that provides some syntax sugar and type mapping. + * + * It mostly forwards the calls to org.mockito.ArgumentMatchers, but with a few improvements to make it more scala-like + * It also renames the "eq" matcher to "eqTo" as in Scala "eq" is a keyword used to do object identity equality + * + * @author Bruno Bonanno + * + */ +trait ArgumentMatchersSugar + extends AnyMatchers + with EqMatchers + with ThatMatchers + with StringThatMatchers + with NullMatchers /** - * Simple object to allow the usage of the trait without mixing it in - * - * @author Bruno Bonanno - * - */ + * Simple object to allow the usage of the trait without mixing it in + * + * @author Bruno Bonanno + * + */ object ArgumentMatchersSugar extends ArgumentMatchersSugar diff --git a/core/src/main/scala/org/mockito/MockitoSugar.scala b/core/src/main/scala/org/mockito/MockitoSugar.scala index ce8f1205..f143d9cd 100644 --- a/core/src/main/scala/org/mockito/MockitoSugar.scala +++ b/core/src/main/scala/org/mockito/MockitoSugar.scala @@ -13,157 +13,164 @@ package org.mockito import org.mockito.MockitoEnhancerUtil.stubMock import org.mockito.MockitoSugar.clazz -import org.mockito.stubbing.{Answer, OngoingStubbing, Stubber} -import org.mockito.verification.{VerificationMode, VerificationWithTimeout} +import org.mockito.stubbing.{ Answer, OngoingStubbing, Stubber } +import org.mockito.verification.{ VerificationMode, VerificationWithTimeout } import scala.collection.JavaConverters._ import scala.reflect.ClassTag import scala.reflect.runtime.universe.TypeTag private[mockito] trait DoSomething { + /** - * Delegates the call to Mockito.doReturn(toBeReturned, toBeReturnedNext) - * but fixes the following compiler issue that happens because the overloaded vararg on the Java side - * - * Error:(33, 25) ambiguous reference to overloaded definition, - * both method doReturn in class Mockito of type (x$1: Any, x$2: Object*)org.mockito.stubbing.Stubber - * and method doReturn in class Mockito of type (x$1: Any)org.mockito.stubbing.Stubber - * match argument types (`Type`) - * - */ + * Delegates the call to Mockito.doReturn(toBeReturned, toBeReturnedNext) + * but fixes the following compiler issue that happens because the overloaded vararg on the Java side + * + * Error:(33, 25) ambiguous reference to overloaded definition, + * both method doReturn in class Mockito of type (x$1: Any, x$2: Object*)org.mockito.stubbing.Stubber + * and method doReturn in class Mockito of type (x$1: Any)org.mockito.stubbing.Stubber + * match argument types (`Type`) + * + */ def doReturn[T](toBeReturned: T, toBeReturnedNext: T*): Stubber = - Mockito.doReturn(toBeReturned, toBeReturnedNext.map(_.asInstanceOf[Object]): _*) + Mockito.doReturn( + toBeReturned, + toBeReturnedNext.map(_.asInstanceOf[Object]): _* + ) /** - * Delegates to Mockito.doThrow, it's only here so we expose all the Mockito API - * on a single place - */ + * Delegates to Mockito.doThrow, it's only here so we expose all the Mockito API + * on a single place + */ def doThrow(toBeThrown: Throwable*): Stubber = Mockito.doThrow(toBeThrown: _*) /** - * Delegates to Mockito.doThrow(type: Class[T]) - * It provides a nicer API as you can, for instance, do doThrow[Throwable] instead of doThrow(classOf[Throwable]) - * - */ - def doThrow[T <: Throwable : ClassTag]: Stubber = Mockito.doThrow(clazz) + * Delegates to Mockito.doThrow(type: Class[T]) + * It provides a nicer API as you can, for instance, do doThrow[Throwable] instead of doThrow(classOf[Throwable]) + * + */ + def doThrow[T <: Throwable: ClassTag]: Stubber = Mockito.doThrow(clazz) /** - * Delegates to Mockito.doNothing(), it removes the parenthesis to have a cleaner API - */ + * Delegates to Mockito.doNothing(), it removes the parenthesis to have a cleaner API + */ def doNothing: Stubber = Mockito.doNothing() /** - * Delegates to Mockito.doCallRealMethod(), it removes the parenthesis to have a cleaner API - */ + * Delegates to Mockito.doCallRealMethod(), it removes the parenthesis to have a cleaner API + */ def doCallRealMethod: Stubber = Mockito.doCallRealMethod() /** - * Delegates to Mockito.doAnswer(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.doAnswer(), it's only here to expose the full Mockito API + */ def doAnswer(answer: Answer[_]): Stubber = Mockito.doAnswer(answer) } private[mockito] trait MockitoEnhancer { + /** - * Delegates to Mockito.mock(type: Class[T]) - * It provides a nicer API as you can, for instance, do mock[MyClass] - * instead of mock(classOf[MyClass]) - * - * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments - * are called, ie: - * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") - * - * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") - * then you could have not verified it like - * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") - * as the value for the second parameter would have been null... - */ - def mock[T <: AnyRef : ClassTag : TypeTag]: T = mock(withSettings) - - /** - * Delegates to Mockito.mock(type: Class[T], defaultAnswer: Answer[_]) - * It provides a nicer API as you can, for instance, do mock[MyClass](defaultAnswer) - * instead of mock(classOf[MyClass], defaultAnswer) - * - * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments - * are called, ie: - * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") - * - * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") - * then you could have not verified it like - * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") - * as the value for the second parameter would have been null... - */ - def mock[T <: AnyRef : ClassTag : TypeTag](defaultAnswer: Answer[_]): T = mock(withSettings.defaultAnswer(defaultAnswer)) - - /** - * Delegates to Mockito.mock(type: Class[T], mockSettings: MockSettings) - * It provides a nicer API as you can, for instance, do mock[MyClass](mockSettings) - * instead of mock(classOf[MyClass], mockSettings) - * - * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments - * are called, ie: - * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") - * - * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") - * then you could have not verified it like - * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") - * as the value for the second parameter would have been null... - */ - def mock[T <: AnyRef : ClassTag : TypeTag](mockSettings: MockSettings): T = { + * Delegates to Mockito.mock(type: Class[T]) + * It provides a nicer API as you can, for instance, do mock[MyClass] + * instead of mock(classOf[MyClass]) + * + * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments + * are called, ie: + * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") + * + * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") + * then you could have not verified it like + * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") + * as the value for the second parameter would have been null... + */ + def mock[T <: AnyRef: ClassTag: TypeTag]: T = mock(withSettings) + + /** + * Delegates to Mockito.mock(type: Class[T], defaultAnswer: Answer[_]) + * It provides a nicer API as you can, for instance, do mock[MyClass](defaultAnswer) + * instead of mock(classOf[MyClass], defaultAnswer) + * + * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments + * are called, ie: + * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") + * + * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") + * then you could have not verified it like + * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") + * as the value for the second parameter would have been null... + */ + def mock[T <: AnyRef: ClassTag: TypeTag](defaultAnswer: Answer[_]): T = + mock(withSettings.defaultAnswer(defaultAnswer)) + + /** + * Delegates to Mockito.mock(type: Class[T], mockSettings: MockSettings) + * It provides a nicer API as you can, for instance, do mock[MyClass](mockSettings) + * instead of mock(classOf[MyClass], mockSettings) + * + * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments + * are called, ie: + * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") + * + * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") + * then you could have not verified it like + * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") + * as the value for the second parameter would have been null... + */ + def mock[T <: AnyRef: ClassTag: TypeTag](mockSettings: MockSettings): T = { val interfaces = ReflectionUtils.interfaces - val settings = if (interfaces.nonEmpty) mockSettings.extraInterfaces(interfaces: _*) else mockSettings + val settings = + if (interfaces.nonEmpty) mockSettings.extraInterfaces(interfaces: _*) + else mockSettings stubMock(Mockito.mock(clazz, settings)) } /** - * Delegates to Mockito.mock(type: Class[T], name: String) - * It provides a nicer API as you can, for instance, do mock[MyClass](name) - * instead of mock(classOf[MyClass], name) - * - * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments - * are called, ie: - * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") - * - * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") - * then you could have not verified it like - * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") - * as the value for the second parameter would have been null... - */ - def mock[T <: AnyRef : ClassTag : TypeTag](name: String): T = mock(withSettings.name(name)) - - - /** - * Delegates to Mockito.reset(T... mocks), but restores the default stubs that - * deal with default argument values - */ + * Delegates to Mockito.mock(type: Class[T], name: String) + * It provides a nicer API as you can, for instance, do mock[MyClass](name) + * instead of mock(classOf[MyClass], name) + * + * It also pre-stub the mock so the compiler-generated methods that provide the values for the default arguments + * are called, ie: + * given def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value") + * + * without this fix, if you call it as iHaveSomeDefaultArguments("I'm not gonna pass the second argument") + * then you could have not verified it like + * verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") + * as the value for the second parameter would have been null... + */ + def mock[T <: AnyRef: ClassTag: TypeTag](name: String): T = + mock(withSettings.name(name)) + + /** + * Delegates to Mockito.reset(T... mocks), but restores the default stubs that + * deal with default argument values + */ def reset(mocks: AnyRef*): Unit = { Mockito.reset(mocks: _*) mocks.foreach(stubMock) } /** - * Delegates to Mockito.mockingDetails(), it's only here to expose the full Mockito API - */ - def mockingDetails(toInspect: AnyRef): MockingDetails = Mockito.mockingDetails(toInspect) + * Delegates to Mockito.mockingDetails(), it's only here to expose the full Mockito API + */ + def mockingDetails(toInspect: AnyRef): MockingDetails = + Mockito.mockingDetails(toInspect) /** - * Delegates to Mockito.withSettings(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.withSettings(), it's only here to expose the full Mockito API + */ def withSettings: MockSettings = Mockito.withSettings() - /** - * Delegates to Mockito.verifyNoMoreInteractions(Object... mocks), but ignores the default stubs that - * deal with default argument values - */ + * Delegates to Mockito.verifyNoMoreInteractions(Object... mocks), but ignores the default stubs that + * deal with default argument values + */ def verifyNoMoreInteractions(mocks: AnyRef*): Unit = { mocks.foreach { m => - mockingDetails(m) - .getInvocations.asScala + mockingDetails(m).getInvocations.asScala .filter(_.getMethod.getName.contains("$default$")) .foreach(_.ignoreForVerification()) } @@ -175,116 +182,125 @@ private[mockito] trait MockitoEnhancer { private[mockito] trait Verifications { /** - * Delegates to Mockito.atLeastOnce(), it removes the parenthesis to have a cleaner API - */ + * Delegates to Mockito.atLeastOnce(), it removes the parenthesis to have a cleaner API + */ def atLeastOnce: VerificationMode = Mockito.atLeastOnce() /** - * Delegates to Mockito.never(), it removes the parenthesis to have a cleaner API - */ + * Delegates to Mockito.never(), it removes the parenthesis to have a cleaner API + */ def never: VerificationMode = Mockito.never() /** - * Delegates to Mockito.only(), it removes the parenthesis to have a cleaner API - */ + * Delegates to Mockito.only(), it removes the parenthesis to have a cleaner API + */ def only: VerificationMode = Mockito.only() /** - * Delegates to Mockito.timeout(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.timeout(), it's only here to expose the full Mockito API + */ def timeout(millis: Int): VerificationWithTimeout = Mockito.timeout(millis) /** - * Delegates to Mockito.times(), it's only here to expose the full Mockito API - */ - def times(wantedNumberOfInvocations: Int): VerificationMode = Mockito.times(wantedNumberOfInvocations) + * Delegates to Mockito.times(), it's only here to expose the full Mockito API + */ + def times(wantedNumberOfInvocations: Int): VerificationMode = + Mockito.times(wantedNumberOfInvocations) /** - * Delegates to Mockito.calls(), it's only here to expose the full Mockito API - */ - def calls(wantedNumberOfInvocations: Int): VerificationMode = Mockito.calls(wantedNumberOfInvocations) + * Delegates to Mockito.calls(), it's only here to expose the full Mockito API + */ + def calls(wantedNumberOfInvocations: Int): VerificationMode = + Mockito.calls(wantedNumberOfInvocations) /** - * Delegates to Mockito.atMost(), it's only here to expose the full Mockito API - */ - def atMost(maxNumberOfInvocations: Int): VerificationMode = Mockito.atMost(maxNumberOfInvocations) + * Delegates to Mockito.atMost(), it's only here to expose the full Mockito API + */ + def atMost(maxNumberOfInvocations: Int): VerificationMode = + Mockito.atMost(maxNumberOfInvocations) /** - * Delegates to Mockito.atLeast(), it's only here to expose the full Mockito API - */ - def atLeast(minNumberOfInvocations: Int): VerificationMode = Mockito.atLeast(minNumberOfInvocations) + * Delegates to Mockito.atLeast(), it's only here to expose the full Mockito API + */ + def atLeast(minNumberOfInvocations: Int): VerificationMode = + Mockito.atLeast(minNumberOfInvocations) } /** - * Trait that provides some basic syntax sugar. - * - * The idea is based on org.scalatest.mockito.MockitoSugar but it adds 100% of the Mockito API - * - * It also solve problems like overloaded varargs calls to Java code and pre-stub the mocks so the default arguments - * in the method parameters work as expected - * - * @author Bruno Bonanno - */ + * Trait that provides some basic syntax sugar. + * + * The idea is based on org.scalatest.mockito.MockitoSugar but it adds 100% of the Mockito API + * + * It also solve problems like overloaded varargs calls to Java code and pre-stub the mocks so the default arguments + * in the method parameters work as expected + * + * @author Bruno Bonanno + */ trait MockitoSugar extends MockitoEnhancer with DoSomething with Verifications { /** - * Delegates to ArgumentCaptor.forClass(type: Class[T]) - * It provides a nicer API as you can, for instance, do argumentCaptor[SomeClass] - * instead of ArgumentCaptor.forClass(classOf[SomeClass]) - */ - def argumentCaptor[T <: AnyRef : ClassTag]: ArgumentCaptor[T] = ArgumentCaptor.forClass(clazz) + * Delegates to ArgumentCaptor.forClass(type: Class[T]) + * It provides a nicer API as you can, for instance, do argumentCaptor[SomeClass] + * instead of ArgumentCaptor.forClass(classOf[SomeClass]) + */ + def argumentCaptor[T <: AnyRef: ClassTag]: ArgumentCaptor[T] = + ArgumentCaptor.forClass(clazz) /** - * Delegates to Mockito.spy(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.spy(), it's only here to expose the full Mockito API + */ def spy[T](realObj: T): T = Mockito.spy(realObj) /** - * Creates a "spy" in a way that supports lambdas and anonymous classes as they don't work with the standard spy as - * they are created as final classes by the compiler - */ - def spyLambda[T <: AnyRef : ClassTag](realObj: T): T = Mockito.mock(clazz, AdditionalAnswers.delegatesTo(realObj)) + * Creates a "spy" in a way that supports lambdas and anonymous classes as they don't work with the standard spy as + * they are created as final classes by the compiler + */ + def spyLambda[T <: AnyRef: ClassTag](realObj: T): T = + Mockito.mock(clazz, AdditionalAnswers.delegatesTo(realObj)) /** - * Delegates to Mockito.when(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.when(), it's only here to expose the full Mockito API + */ def when[T](methodCall: T): OngoingStubbing[T] = Mockito.when(methodCall) /** - * Delegates to Mockito.ignoreStubs(), it's only here to expose the full Mockito API - */ - def ignoreStubs(mocks: AnyRef*): Array[AnyRef] = Mockito.ignoreStubs(mocks: _*) + * Delegates to Mockito.ignoreStubs(), it's only here to expose the full Mockito API + */ + def ignoreStubs(mocks: AnyRef*): Array[AnyRef] = + Mockito.ignoreStubs(mocks: _*) /** - * Delegates to Mockito.validateMockitoUsage(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.validateMockitoUsage(), it's only here to expose the full Mockito API + */ def validateMockitoUsage(): Unit = Mockito.validateMockitoUsage() /** - * Delegates to Mockito.verifyZeroInteractions(), it's only here to expose the full Mockito API - */ - def verifyZeroInteractions(mocks: AnyRef*): Unit = Mockito.verifyZeroInteractions(mocks: _*) + * Delegates to Mockito.verifyZeroInteractions(), it's only here to expose the full Mockito API + */ + def verifyZeroInteractions(mocks: AnyRef*): Unit = + Mockito.verifyZeroInteractions(mocks: _*) /** - * Delegates to Mockito.inOrder(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.inOrder(), it's only here to expose the full Mockito API + */ def inOrder(mocks: AnyRef*): InOrder = Mockito.inOrder(mocks: _*) /** - * Delegates to Mockito.verify(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.verify(), it's only here to expose the full Mockito API + */ def verify[T](mock: T): T = Mockito.verify(mock) /** - * Delegates to Mockito.verify(), it's only here to expose the full Mockito API - */ + * Delegates to Mockito.verify(), it's only here to expose the full Mockito API + */ def verify[T](mock: T, mode: VerificationMode): T = Mockito.verify(mock, mode) } /** - * Simple object to allow the usage of the trait without mixing it in - */ + * Simple object to allow the usage of the trait without mixing it in + */ object MockitoSugar extends MockitoSugar { - private[mockito] def clazz[T <: AnyRef](implicit classTag: ClassTag[T]) = classTag.runtimeClass.asInstanceOf[Class[T]] + private[mockito] def clazz[T <: AnyRef](implicit classTag: ClassTag[T]) = + classTag.runtimeClass.asInstanceOf[Class[T]] } diff --git a/core/src/main/scala/org/mockito/ReflectionUtils.scala b/core/src/main/scala/org/mockito/ReflectionUtils.scala index 9efb9b14..61fda4f1 100644 --- a/core/src/main/scala/org/mockito/ReflectionUtils.scala +++ b/core/src/main/scala/org/mockito/ReflectionUtils.scala @@ -6,9 +6,10 @@ private[mockito] object ReflectionUtils { def interfaces[T](implicit tag: TypeTag[T]): List[Class[_]] = tag.tpe match { - case RefinedType(types, _) => types.map(tag.mirror.runtimeClass).collect { - case c: Class[_] if c.isInterface => c - } + case RefinedType(types, _) => + types.map(tag.mirror.runtimeClass).collect { + case c: Class[_] if c.isInterface => c + } case _ => List.empty } diff --git a/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala b/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala index 8cac8aee..faef301b 100644 --- a/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala @@ -14,67 +14,68 @@ package org.mockito.matchers import org.mockito.{ArgumentMatchers => JavaMatchers} private[mockito] trait AnyMatchers { - /** List matcher that use Scala List to avoid compile errors like - * Error:(40, 60) type mismatch; - * found : List[String] (in java.util) - * required: List[?] (in scala.collection.immutable) - * - * when trying to do something like ArgumentMatchers.anyList[String]() - * - */ - def anyList[T]: List[T] = any[List[T]] - /** Seq matcher that use Scala Seq to avoid compile errors like - * Error:(40, 60) type mismatch; - * found : List[String] (in java.util) - * required: Seq[?] (in scala.collection.immutable) - * - * when trying to do something like ArgumentMatchers.anyList[String]() - * - */ - def anySeq[T]: Seq[T] = any[Seq[T]] - - /** Iterable matcher that use Scala Iterable to avoid compile errors like - * Error:(40, 60) type mismatch; - * found : Iterable[String] (in java.util) - * required: Iterable[?] (in scala.collection.immutable) - * - * when trying to do something like ArgumentMatchers.anyIterable[String]() - * - */ - def anyIterable[T]: Iterable[T] = any[Iterable[T]] - - /** Set matcher that use Scala Set to avoid compile errors like - * Error:(40, 60) type mismatch; - * found : Set[String] (in java.util) - * required: Set[?] (in scala.collection.immutable) - * - * when trying to do something like ArgumentMatchers.anySet[String]() - * - */ - def anySet[T]: Set[T] = any[Set[T]] - - /** Map matcher that use Scala Map to avoid compile errors like - * Error:(40, 60) type mismatch; - * found : Map[String, String] (in java.util) - * required: Map[?] (in scala.collection.immutable) - * - * when trying to do something like ArgumentMatchers.anyMap[String, String]() - * - */ - def anyMap[K, V]: Map[K, V] = any[Map[K, V]] - - /** - * Delegates to ArgumentMatchers.any(), it's main purpose is to remove the () out of - * the method call, if you try to do that directly on the test you get this error - * - * Error:(71, 46) polymorphic expression cannot be instantiated to expected type; - * found : [T]()T - * required: String - * when you try to something like ArgumentMatchers.any - * - */ - def any[T]: T = JavaMatchers.any[T]() + /** List matcher that use Scala List to avoid compile errors like + * Error:(40, 60) type mismatch; + * found : List[String] (in java.util) + * required: List[?] (in scala.collection.immutable) + * + * when trying to do something like ArgumentMatchers.anyList[String]() + * + */ + def anyList[T]: List[T] = any[List[T]] + + /** Seq matcher that use Scala Seq to avoid compile errors like + * Error:(40, 60) type mismatch; + * found : List[String] (in java.util) + * required: Seq[?] (in scala.collection.immutable) + * + * when trying to do something like ArgumentMatchers.anyList[String]() + * + */ + def anySeq[T]: Seq[T] = any[Seq[T]] + + /** Iterable matcher that use Scala Iterable to avoid compile errors like + * Error:(40, 60) type mismatch; + * found : Iterable[String] (in java.util) + * required: Iterable[?] (in scala.collection.immutable) + * + * when trying to do something like ArgumentMatchers.anyIterable[String]() + * + */ + def anyIterable[T]: Iterable[T] = any[Iterable[T]] + + /** Set matcher that use Scala Set to avoid compile errors like + * Error:(40, 60) type mismatch; + * found : Set[String] (in java.util) + * required: Set[?] (in scala.collection.immutable) + * + * when trying to do something like ArgumentMatchers.anySet[String]() + * + */ + def anySet[T]: Set[T] = any[Set[T]] + + /** Map matcher that use Scala Map to avoid compile errors like + * Error:(40, 60) type mismatch; + * found : Map[String, String] (in java.util) + * required: Map[?] (in scala.collection.immutable) + * + * when trying to do something like ArgumentMatchers.anyMap[String, String]() + * + */ + def anyMap[K, V]: Map[K, V] = any[Map[K, V]] + + /** + * Delegates to ArgumentMatchers.any(), it's main purpose is to remove the () out of + * the method call, if you try to do that directly on the test you get this error + * + * Error:(71, 46) polymorphic expression cannot be instantiated to expected type; + * found : [T]()T + * required: String + * when you try to something like ArgumentMatchers.any + * + */ + def any[T]: T = JavaMatchers.any[T]() /** * Delegates to ArgumentMatchers.anyByte(), it's only here so we expose all the `ArgumentMatchers` @@ -83,52 +84,52 @@ private[mockito] trait AnyMatchers { */ def anyByte: Byte = JavaMatchers.anyByte - /** - * Delegates to ArgumentMatchers.anyBoolean(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyBoolean: Boolean = JavaMatchers.anyBoolean - - /** - * Delegates to ArgumentMatchers.anyChar(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyChar: Char = JavaMatchers.anyChar - - /** - * Delegates to ArgumentMatchers.anyDouble(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyDouble: Double = JavaMatchers.anyDouble - - /** - * Delegates to ArgumentMatchers.anyInt(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyInt: Int = JavaMatchers.anyInt - - /** - * Delegates to ArgumentMatchers.anyFloat(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyFloat: Float = JavaMatchers.anyFloat - - /** - * Delegates to ArgumentMatchers.anyShort(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyShort: Short = JavaMatchers.anyShort - - /** - * Delegates to ArgumentMatchers.anyLong(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyLong: Long = JavaMatchers.anyLong + /** + * Delegates to ArgumentMatchers.anyBoolean(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyBoolean: Boolean = JavaMatchers.anyBoolean + + /** + * Delegates to ArgumentMatchers.anyChar(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyChar: Char = JavaMatchers.anyChar + + /** + * Delegates to ArgumentMatchers.anyDouble(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyDouble: Double = JavaMatchers.anyDouble + + /** + * Delegates to ArgumentMatchers.anyInt(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyInt: Int = JavaMatchers.anyInt + + /** + * Delegates to ArgumentMatchers.anyFloat(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyFloat: Float = JavaMatchers.anyFloat + + /** + * Delegates to ArgumentMatchers.anyShort(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyShort: Short = JavaMatchers.anyShort + + /** + * Delegates to ArgumentMatchers.anyLong(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyLong: Long = JavaMatchers.anyLong } diff --git a/core/src/main/scala/org/mockito/matchers/EqMatchers.scala b/core/src/main/scala/org/mockito/matchers/EqMatchers.scala index 930b74e3..d09082d4 100644 --- a/core/src/main/scala/org/mockito/matchers/EqMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/EqMatchers.scala @@ -11,36 +11,39 @@ package org.mockito.matchers -import org.mockito.{ArgumentMatchers => JavaMatchers} +import org.mockito.{ ArgumentMatchers => JavaMatchers } import scala.reflect.ClassTag private[mockito] trait EqMatchers { - /** - * Delegates to ArgumentMatchers.eq(), it renames the method to eqTo to - * avoid clashes with the Scala eq method used for reference equality - * - */ - def eqTo[T](value: T): T = JavaMatchers.eq(value) - - /** - * Delegates to ArgumentMatchers.same(), it's only here so we expose all the `ArgumentMatchers` - * on a single place - * - */ - def same[T](value: T): T = JavaMatchers.same(value) - - /** - * Delegates to ArgumentMatchers.isA(type: Class[T]) - * It provides a nicer API as you can, for instance, do isA[String] instead of isA(classOf[String]) - * - */ - def isA[T](implicit classTag: ClassTag[T]): T = JavaMatchers.isA(classTag.runtimeClass.asInstanceOf[Class[T]]) - - /** - * Delegates to ArgumentMatchers.refEq(), it's only here so we expose all the `ArgumentMatchers` - * on a single place - * - */ - def refEq[T](value: T, excludeFields: String*): T = JavaMatchers.refEq(value, excludeFields: _*) + + /** + * Delegates to ArgumentMatchers.eq(), it renames the method to eqTo to + * avoid clashes with the Scala eq method used for reference equality + * + */ + def eqTo[T](value: T): T = JavaMatchers.eq(value) + + /** + * Delegates to ArgumentMatchers.same(), it's only here so we expose all the `ArgumentMatchers` + * on a single place + * + */ + def same[T](value: T): T = JavaMatchers.same(value) + + /** + * Delegates to ArgumentMatchers.isA(type: Class[T]) + * It provides a nicer API as you can, for instance, do isA[String] instead of isA(classOf[String]) + * + */ + def isA[T](implicit classTag: ClassTag[T]): T = + JavaMatchers.isA(classTag.runtimeClass.asInstanceOf[Class[T]]) + + /** + * Delegates to ArgumentMatchers.refEq(), it's only here so we expose all the `ArgumentMatchers` + * on a single place + * + */ + def refEq[T](value: T, excludeFields: String*): T = + JavaMatchers.refEq(value, excludeFields: _*) } diff --git a/core/src/main/scala/org/mockito/matchers/NullMatchers.scala b/core/src/main/scala/org/mockito/matchers/NullMatchers.scala index d2225fc8..30e3ac81 100644 --- a/core/src/main/scala/org/mockito/matchers/NullMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/NullMatchers.scala @@ -11,24 +11,25 @@ package org.mockito.matchers -import org.mockito.{ArgumentMatchers => JavaMatchers} +import org.mockito.{ ArgumentMatchers => JavaMatchers } private[mockito] trait NullMatchers { - /** - * Delegates to ArgumentMatchers.isNull(), it's only here so we expose all the `ArgumentMatchers` - * on a single place, but marked as @deprecated as you shouldn't be testing for nulls - * on Scala - * - */ - @deprecated - def isNull[T]: T = JavaMatchers.isNull[T] - /** - * Delegates to ArgumentMatchers.isNotNull(), it's only here so we expose all the `ArgumentMatchers` - * on a single place, but marked as @deprecated as you shouldn't be testing for nulls - * on Scala - * - */ - @deprecated - def isNotNull[T]: T = JavaMatchers.isNotNull[T] + /** + * Delegates to ArgumentMatchers.isNull(), it's only here so we expose all the `ArgumentMatchers` + * on a single place, but marked as @deprecated as you shouldn't be testing for nulls + * on Scala + * + */ + @deprecated + def isNull[T]: T = JavaMatchers.isNull[T] + + /** + * Delegates to ArgumentMatchers.isNotNull(), it's only here so we expose all the `ArgumentMatchers` + * on a single place, but marked as @deprecated as you shouldn't be testing for nulls + * on Scala + * + */ + @deprecated + def isNotNull[T]: T = JavaMatchers.isNotNull[T] } diff --git a/core/src/main/scala/org/mockito/matchers/StringThatMatchers.scala b/core/src/main/scala/org/mockito/matchers/StringThatMatchers.scala index 30d271f0..fe2a1386 100644 --- a/core/src/main/scala/org/mockito/matchers/StringThatMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/StringThatMatchers.scala @@ -11,34 +11,35 @@ package org.mockito.matchers -import org.mockito.{ArgumentMatchers => JavaMatchers} +import org.mockito.{ ArgumentMatchers => JavaMatchers } private[mockito] trait StringThatMatchers { - /** - * Delegates to ArgumentMatchers.matches(), it's only here so we expose all the `ArgumentMatchers` - * on a single place - * - */ - def matches(regex: String): String = JavaMatchers.matches(regex) - /** - * Delegates to ArgumentMatchers.startsWith(), it's only here so we expose all the `ArgumentMatchers` - * on a single place - * - */ - def startsWith(prefix: String): String = JavaMatchers.startsWith(prefix) + /** + * Delegates to ArgumentMatchers.matches(), it's only here so we expose all the `ArgumentMatchers` + * on a single place + * + */ + def matches(regex: String): String = JavaMatchers.matches(regex) - /** - * Delegates to ArgumentMatchers.contains(), it's only here so we expose all the `ArgumentMatchers` - * on a single place - * - */ - def contains(substring: String): String = JavaMatchers.contains(substring) + /** + * Delegates to ArgumentMatchers.startsWith(), it's only here so we expose all the `ArgumentMatchers` + * on a single place + * + */ + def startsWith(prefix: String): String = JavaMatchers.startsWith(prefix) - /** - * Delegates to ArgumentMatchers.endsWith(), it's only here so we expose all the `ArgumentMatchers` - * on a single place - * - */ - def endsWith(suffix: String): String = JavaMatchers.endsWith(suffix) + /** + * Delegates to ArgumentMatchers.contains(), it's only here so we expose all the `ArgumentMatchers` + * on a single place + * + */ + def contains(substring: String): String = JavaMatchers.contains(substring) + + /** + * Delegates to ArgumentMatchers.endsWith(), it's only here so we expose all the `ArgumentMatchers` + * on a single place + * + */ + def endsWith(suffix: String): String = JavaMatchers.endsWith(suffix) } diff --git a/core/src/main/scala/org/mockito/matchers/ThatMatchers.scala b/core/src/main/scala/org/mockito/matchers/ThatMatchers.scala index 017eaa21..1c15bc95 100644 --- a/core/src/main/scala/org/mockito/matchers/ThatMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/ThatMatchers.scala @@ -11,79 +11,79 @@ package org.mockito.matchers -import org.mockito.{ArgumentMatcher, ArgumentMatchers => JavaMatchers} +import org.mockito.{ ArgumentMatcher, ArgumentMatchers => JavaMatchers } private[mockito] trait ThatMatchers { - /** - * Delegates to ArgumentMatchers.argThat(matcher), it's only here so we expose all the `ArgumentMatchers` - * on a single place - * - */ - def argThat[T](matcher: ArgumentMatcher[T]): T = JavaMatchers.argThat(matcher) + /** + * Delegates to ArgumentMatchers.argThat(matcher), it's only here so we expose all the `ArgumentMatchers` + * on a single place + * + */ + def argThat[T](matcher: ArgumentMatcher[T]): T = JavaMatchers.argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitives", this - * provides avoids an unnecessary implicit conversion that would be necessary if we used - * the Java version - * - */ - def byteThat(matcher: ArgumentMatcher[Byte]): Byte = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitives", this + * provides avoids an unnecessary implicit conversion that would be necessary if we used + * the Java version + * + */ + def byteThat(matcher: ArgumentMatcher[Byte]): Byte = argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitive", this - * provides avoids an unnecessary implicit conversion that would be necessary if we used - * the Java version - * - */ - def booleanThat(matcher: ArgumentMatcher[Boolean]): Boolean = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitive", this + * provides avoids an unnecessary implicit conversion that would be necessary if we used + * the Java version + * + */ + def booleanThat(matcher: ArgumentMatcher[Boolean]): Boolean = argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitive", this - * provides avoids an unnecessary implicit conversion that would be necessary if we used - * the Java version - * - */ - def charThat(matcher: ArgumentMatcher[Char]): Char = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitive", this + * provides avoids an unnecessary implicit conversion that would be necessary if we used + * the Java version + * + */ + def charThat(matcher: ArgumentMatcher[Char]): Char = argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitive", this - * provides avoids an unnecessary implicit conversion that would be necessary if we used - * the Java version - * - */ - def doubleThat(matcher: ArgumentMatcher[Double]): Double = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitive", this + * provides avoids an unnecessary implicit conversion that would be necessary if we used + * the Java version + * + */ + def doubleThat(matcher: ArgumentMatcher[Double]): Double = argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitive", this - * provides avoids an unnecessary implicit conversion that would be necessary if we used - * the Java version - * - */ - def intThat(matcher: ArgumentMatcher[Int]): Int = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitive", this + * provides avoids an unnecessary implicit conversion that would be necessary if we used + * the Java version + * + */ + def intThat(matcher: ArgumentMatcher[Int]): Int = argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitive", this - * provides avoids an unnecessary implicit conversion that would be necessary if we used - * the Java version - * - */ - def floatThat(matcher: ArgumentMatcher[Float]): Float = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitive", this + * provides avoids an unnecessary implicit conversion that would be necessary if we used + * the Java version + * + */ + def floatThat(matcher: ArgumentMatcher[Float]): Float = argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitive", this - * provides avoids an unnecessary implicit conversion that would be necessary if we used - * the Java version - * - */ - def shortThat(matcher: ArgumentMatcher[Short]): Short = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitive", this + * provides avoids an unnecessary implicit conversion that would be necessary if we used + * the Java version + * + */ + def shortThat(matcher: ArgumentMatcher[Short]): Short = argThat(matcher) - /** - * Delegates the call to argThat but using the Scala "primitive", this - * provides avoids an unnecessary conversion that would be necessary used - * the Java version - * - */ - def longThat(matcher: ArgumentMatcher[Long]): Long = argThat(matcher) + /** + * Delegates the call to argThat but using the Scala "primitive", this + * provides avoids an unnecessary conversion that would be necessary used + * the Java version + * + */ + def longThat(matcher: ArgumentMatcher[Long]): Long = argThat(matcher) } diff --git a/core/src/test/scala/org/mockito/DoSomethingTest.scala b/core/src/test/scala/org/mockito/DoSomethingTest.scala index c37e4418..4e82c0e0 100644 --- a/core/src/test/scala/org/mockito/DoSomethingTest.scala +++ b/core/src/test/scala/org/mockito/DoSomethingTest.scala @@ -1,142 +1,142 @@ package org.mockito -import org.scalatest.{FlatSpec, Matchers => ScalaTestMatchers} - +import org.scalatest.{ FlatSpec, Matchers => ScalaTestMatchers } class DoSomethingTest extends FlatSpec with MockitoSugar with ScalaTestMatchers { - class Foo { - def bar = "not mocked" + class Foo { + def bar = "not mocked" - def returnDouble: Double = 10 + def returnDouble: Double = 10 - def returnFloat: Float = 10 + def returnFloat: Float = 10 - def returnLong: Long = 10 + def returnLong: Long = 10 - def returnInt: Int = 10 + def returnInt: Int = 10 - def returnShort: Short = 10 + def returnShort: Short = 10 - def returnByte: Byte = 10 + def returnByte: Byte = 10 - def returnChar: Char = 'a' + def returnChar: Char = 'a' - def returnBoolean: Boolean = true + def returnBoolean: Boolean = true - def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value"): String = s"$noDefault - $default" - } + def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value"): String = + s"$noDefault - $default" + } - "doCallRealMethod" should "work as normal" in { - val aMock = mock[Foo] + "doCallRealMethod" should "work as normal" in { + val aMock = mock[Foo] - doCallRealMethod.when(aMock).bar + doCallRealMethod.when(aMock).bar - aMock.bar shouldBe "not mocked" - } + aMock.bar shouldBe "not mocked" + } - "doAnswer" should "work as normal" in { - val aMock = mock[Foo] + "doAnswer" should "work as normal" in { + val aMock = mock[Foo] - doAnswer(_ => "mocked!").when(aMock).bar + doAnswer(_ => "mocked!").when(aMock).bar - aMock.bar shouldBe "mocked!" - } + aMock.bar shouldBe "mocked!" + } - "doReturn(toBeReturned)" should "not fail with overloading issues" in { - val aMock = mock[Foo] + "doReturn(toBeReturned)" should "not fail with overloading issues" in { + val aMock = mock[Foo] - doReturn("mocked!").when(aMock).bar + doReturn("mocked!").when(aMock).bar - aMock.bar shouldBe "mocked!" - } + aMock.bar shouldBe "mocked!" + } - "doReturn(toBeReturned, toBeReturnedNext)" should "not fail with overloading issues" in { - val aMock = mock[Foo] + "doReturn(toBeReturned, toBeReturnedNext)" should "not fail with overloading issues" in { + val aMock = mock[Foo] - doReturn("mocked!", "mocked again!").when(aMock).bar + doReturn("mocked!", "mocked again!").when(aMock).bar - aMock.bar shouldBe "mocked!" - aMock.bar shouldBe "mocked again!" - } + aMock.bar shouldBe "mocked!" + aMock.bar shouldBe "mocked again!" + } - "doReturn(toBeReturned)" should "work with AnyVals" in { - val aMock = mock[Foo] + "doReturn(toBeReturned)" should "work with AnyVals" in { + val aMock = mock[Foo] - doReturn(999d).when(aMock).returnDouble - aMock.returnDouble shouldBe 999 + doReturn(999d).when(aMock).returnDouble + aMock.returnDouble shouldBe 999 - doReturn(999f).when(aMock).returnFloat - aMock.returnFloat shouldBe 999 + doReturn(999f).when(aMock).returnFloat + aMock.returnFloat shouldBe 999 - doReturn(999l).when(aMock).returnLong - aMock.returnLong shouldBe 999 + doReturn(999l).when(aMock).returnLong + aMock.returnLong shouldBe 999 - doReturn(999).when(aMock).returnInt - aMock.returnInt shouldBe 999 + doReturn(999).when(aMock).returnInt + aMock.returnInt shouldBe 999 - doReturn(255.toShort).when(aMock).returnShort - aMock.returnShort shouldBe 255 + doReturn(255.toShort).when(aMock).returnShort + aMock.returnShort shouldBe 255 - doReturn(128.toByte).when(aMock).returnByte - aMock.returnByte shouldBe 128.toByte + doReturn(128.toByte).when(aMock).returnByte + aMock.returnByte shouldBe 128.toByte - doReturn('c').when(aMock).returnChar - aMock.returnChar shouldBe 'c' + doReturn('c').when(aMock).returnChar + aMock.returnChar shouldBe 'c' - doReturn(false).when(aMock).returnBoolean - aMock.returnBoolean shouldBe false - } + doReturn(false).when(aMock).returnBoolean + aMock.returnBoolean shouldBe false + } - "doReturn(toBeReturned, toBeReturnedNext)" should "work with AnyVals" in { - val aMock = mock[Foo] + "doReturn(toBeReturned, toBeReturnedNext)" should "work with AnyVals" in { + val aMock = mock[Foo] - doReturn(999d, 111d).when(aMock).returnDouble - aMock.returnDouble shouldBe 999 - aMock.returnDouble shouldBe 111 + doReturn(999d, 111d).when(aMock).returnDouble + aMock.returnDouble shouldBe 999 + aMock.returnDouble shouldBe 111 - doReturn(999f, 111f).when(aMock).returnFloat - aMock.returnFloat shouldBe 999 - aMock.returnFloat shouldBe 111 + doReturn(999f, 111f).when(aMock).returnFloat + aMock.returnFloat shouldBe 999 + aMock.returnFloat shouldBe 111 - doReturn(999l, 111l).when(aMock).returnLong - aMock.returnLong shouldBe 999 - aMock.returnLong shouldBe 111 + doReturn(999l, 111l).when(aMock).returnLong + aMock.returnLong shouldBe 999 + aMock.returnLong shouldBe 111 - doReturn(999, 111).when(aMock).returnInt - aMock.returnInt shouldBe 999 - aMock.returnInt shouldBe 111 + doReturn(999, 111).when(aMock).returnInt + aMock.returnInt shouldBe 999 + aMock.returnInt shouldBe 111 - doReturn(255.toShort, 111.toShort).when(aMock).returnShort - aMock.returnShort shouldBe 255 - aMock.returnShort shouldBe 111 + doReturn(255.toShort, 111.toShort).when(aMock).returnShort + aMock.returnShort shouldBe 255 + aMock.returnShort shouldBe 111 - doReturn(128.toByte, 111.toByte).when(aMock).returnByte - aMock.returnByte shouldBe 128.toByte - aMock.returnByte shouldBe 111.toByte + doReturn(128.toByte, 111.toByte).when(aMock).returnByte + aMock.returnByte shouldBe 128.toByte + aMock.returnByte shouldBe 111.toByte - doReturn('c', 'z').when(aMock).returnChar - aMock.returnChar shouldBe 'c' - aMock.returnChar shouldBe 'z' + doReturn('c', 'z').when(aMock).returnChar + aMock.returnChar shouldBe 'c' + aMock.returnChar shouldBe 'z' - doReturn(false, true).when(aMock).returnBoolean - aMock.returnBoolean shouldBe false - aMock.returnBoolean shouldBe true - } + doReturn(false, true).when(aMock).returnBoolean + aMock.returnBoolean shouldBe false + aMock.returnBoolean shouldBe true + } - "doThrow" should "work as normal" in { - val aMock = mock[Foo] + "doThrow" should "work as normal" in { + val aMock = mock[Foo] - doThrow(new IllegalArgumentException).when(aMock).bar + doThrow(new IllegalArgumentException).when(aMock).bar - a[IllegalArgumentException] shouldBe thrownBy(aMock.bar) - } + a[IllegalArgumentException] shouldBe thrownBy(aMock.bar) + } - "doThrow[T]" should "work as normal" in { - val aMock = mock[Foo] + "doThrow[T]" should "work as normal" in { + val aMock = mock[Foo] - doThrow[IllegalArgumentException].when(aMock).bar + doThrow[IllegalArgumentException].when(aMock).bar - a[IllegalArgumentException] shouldBe thrownBy(aMock.bar) - } + a[IllegalArgumentException] shouldBe thrownBy(aMock.bar) + } } diff --git a/core/src/test/scala/org/mockito/MockitoSugarTest.scala b/core/src/test/scala/org/mockito/MockitoSugarTest.scala index 484cb3c5..19ffb10c 100644 --- a/core/src/test/scala/org/mockito/MockitoSugarTest.scala +++ b/core/src/test/scala/org/mockito/MockitoSugarTest.scala @@ -8,13 +8,17 @@ class MockitoSugarTest extends WordSpec with MockitoSugar with scalatest.Matcher class Foo { def bar = "not mocked" - def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value"): String = s"$noDefault - $default" + def iHaveSomeDefaultArguments(noDefault: String, default: String = "default value"): String = + s"$noDefault - $default" } class Bar { def baz = "not mocked" - def iAlsoHaveSomeDefaultArguments(noDefault: String, default: String = "default value"): String = s"$noDefault - $default" + def iAlsoHaveSomeDefaultArguments( + noDefault: String, + default: String = "default value" + ): String = s"$noDefault - $default" } trait Baz { @@ -36,10 +40,19 @@ class MockitoSugarTest extends WordSpec with MockitoSugar with scalatest.Matcher val aMock = mock[Foo] aMock.iHaveSomeDefaultArguments("I'm not gonna pass the second argument") - aMock.iHaveSomeDefaultArguments("I'm gonna pass the second argument", "second argument") - - verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") - verify(aMock).iHaveSomeDefaultArguments("I'm gonna pass the second argument", "second argument") + aMock.iHaveSomeDefaultArguments( + "I'm gonna pass the second argument", + "second argument" + ) + + verify(aMock).iHaveSomeDefaultArguments( + "I'm not gonna pass the second argument", + "default value" + ) + verify(aMock).iHaveSomeDefaultArguments( + "I'm gonna pass the second argument", + "second argument" + ) } "create a mock with default answer" in { @@ -81,16 +94,24 @@ class MockitoSugarTest extends WordSpec with MockitoSugar with scalatest.Matcher "reset[T]" should { "reset the mock and re-configure the mock so it works with default arguments" in { - val aMock = mock[Foo] + val aMock = mock[Foo] val anotherMock = mock[Bar] reset(aMock, anotherMock) aMock.iHaveSomeDefaultArguments("I'm not gonna pass the second argument") - anotherMock.iAlsoHaveSomeDefaultArguments("I'm not gonna pass the second argument") - - verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") - verify(anotherMock).iAlsoHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") + anotherMock.iAlsoHaveSomeDefaultArguments( + "I'm not gonna pass the second argument" + ) + + verify(aMock).iHaveSomeDefaultArguments( + "I'm not gonna pass the second argument", + "default value" + ) + verify(anotherMock).iAlsoHaveSomeDefaultArguments( + "I'm not gonna pass the second argument", + "default value" + ) } } @@ -100,7 +121,10 @@ class MockitoSugarTest extends WordSpec with MockitoSugar with scalatest.Matcher aMock.iHaveSomeDefaultArguments("I'm not gonna pass the second argument") - verify(aMock).iHaveSomeDefaultArguments("I'm not gonna pass the second argument", "default value") + verify(aMock).iHaveSomeDefaultArguments( + "I'm not gonna pass the second argument", + "default value" + ) verifyNoMoreInteractions(aMock) } } @@ -113,7 +137,8 @@ class MockitoSugarTest extends WordSpec with MockitoSugar with scalatest.Matcher val captor1 = argumentCaptor[String] val captor2 = argumentCaptor[String] - verify(aMock).iHaveSomeDefaultArguments(captor1.capture(), captor2.capture()) + verify(aMock) + .iHaveSomeDefaultArguments(captor1.capture(), captor2.capture()) captor1.getValue shouldBe "I'm not gonna pass the second argument" captor2.getValue shouldBe "default value" diff --git a/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala index dd2d5860..2e0e7609 100644 --- a/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala +++ b/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala @@ -5,144 +5,145 @@ import org.scalatest.{FlatSpec, Matchers => ScalaTestMatchers} class AnyMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers with AnyMatchers { - class Foo { - def bar[T](v: T): T = v + class Foo { + def bar[T](v: T): T = v - def barTyped(v: String): String = v + def barTyped(v: String): String = v - def barByte(v: Byte): Byte = v + def barByte(v: Byte): Byte = v - def barBoolean(v: Boolean): Boolean = v + def barBoolean(v: Boolean): Boolean = v - def barChar(v: Char): Char = v + def barChar(v: Char): Char = v - def barDouble(v: Double): Double = v + def barDouble(v: Double): Double = v - def barInt(v: Int): Int = v + def barInt(v: Int): Int = v - def barFloat(v: Float): Float = v + def barFloat(v: Float): Float = v - def barShort(v: Short): Short = v + def barShort(v: Short): Short = v - def barLong(v: Long): Long = v + def barLong(v: Long): Long = v + def barList[T](v: List[T]): List[T] = v - def barList[T](v: List[T]): List[T] = v + def barSeq[T](v: Seq[T]): Seq[T] = v - def barSeq[T](v: Seq[T]): Seq[T] = v + def barIterable[T](v: Iterable[T]): Iterable[T] = v - def barIterable[T](v: Iterable[T]): Iterable[T] = v - - def barMap[K, V](v: Map[K, V]): Map[K, V] = v + def barMap[K, V](v: Map[K, V]): Map[K, V] = v def barSet[T](v: Set[T]): Set[T] = v } - "any[Collection]" should "work with Scala types" in { - val aMock = mock[Foo] + "any[Collection]" should "work with Scala types" in { + val aMock = mock[Foo] - when(aMock.barSeq(anySeq[String])) thenReturn Seq("mocked!") - aMock.barSeq(Seq("meh")) shouldBe Seq("mocked!") - verify(aMock).barSeq(Seq("meh")) + when(aMock.barSeq(anySeq[String])) thenReturn Seq("mocked!") + aMock.barSeq(Seq("meh")) shouldBe Seq("mocked!") + verify(aMock).barSeq(Seq("meh")) - when(aMock.barList(anyList[String])) thenReturn List("mocked!") - aMock.barList(List("meh")) shouldBe List("mocked!") - verify(aMock).barList(List("meh")) + when(aMock.barList(anyList[String])) thenReturn List("mocked!") + aMock.barList(List("meh")) shouldBe List("mocked!") + verify(aMock).barList(List("meh")) - when(aMock.barIterable(anyIterable[String])) thenReturn Iterable("mocked!") - aMock.barIterable(Iterable("meh")) shouldBe Iterable("mocked!") - verify(aMock).barIterable(Iterable("meh")) + when(aMock.barIterable(anyIterable[String])) thenReturn Iterable("mocked!") + aMock.barIterable(Iterable("meh")) shouldBe Iterable("mocked!") + verify(aMock).barIterable(Iterable("meh")) - when(aMock.barMap(anyMap[String, String])) thenReturn Map("I am" -> "mocked!") - aMock.barMap(Map.empty) shouldBe Map("I am" -> "mocked!") - verify(aMock).barMap(Map.empty) + when(aMock.barMap(anyMap[String, String])) thenReturn Map( + "I am" -> "mocked!" + ) + aMock.barMap(Map.empty) shouldBe Map("I am" -> "mocked!") + verify(aMock).barMap(Map.empty) - when(aMock.barSet(anySet[String])) thenReturn Set("mocked!") - aMock.barSet(Set("meh")) shouldBe Set("mocked!") - verify(aMock).barSet(Set("meh")) - } + when(aMock.barSet(anySet[String])) thenReturn Set("mocked!") + aMock.barSet(Set("meh")) shouldBe Set("mocked!") + verify(aMock).barSet(Set("meh")) + } - "any" should "work with AnyRef" in { - val aMock = mock[Foo] + "any" should "work with AnyRef" in { + val aMock = mock[Foo] - when(aMock.bar(any)) thenReturn "mocked!" - aMock.bar("meh") shouldBe "mocked!" - verify(aMock).bar("meh") + when(aMock.bar(any)) thenReturn "mocked!" + aMock.bar("meh") shouldBe "mocked!" + verify(aMock).bar("meh") - when(aMock.barTyped(any)) thenReturn "mocked!" - aMock.barTyped("meh") shouldBe "mocked!" - verify(aMock).barTyped("meh") - } + when(aMock.barTyped(any)) thenReturn "mocked!" + aMock.barTyped("meh") shouldBe "mocked!" + verify(aMock).barTyped("meh") + } "any" should "work with AnyVal" in { val aMock = mock[Foo] - when(aMock.barByte(any)) thenReturn 10.toByte - aMock.barByte(1) shouldBe 10 - verify(aMock).barByte(1) + when(aMock.barByte(any)) thenReturn 10.toByte + aMock.barByte(1) shouldBe 10 + verify(aMock).barByte(1) - when(aMock.barBoolean(any)) thenReturn true - aMock.barBoolean(false) shouldBe true - verify(aMock).barBoolean(false) + when(aMock.barBoolean(any)) thenReturn true + aMock.barBoolean(false) shouldBe true + verify(aMock).barBoolean(false) - when(aMock.barChar(any)) thenReturn 'c' - aMock.barChar('a') shouldBe 'c' - verify(aMock).barChar('a') + when(aMock.barChar(any)) thenReturn 'c' + aMock.barChar('a') shouldBe 'c' + verify(aMock).barChar('a') - when(aMock.barDouble(any)) thenReturn 100d - aMock.barDouble(1d) shouldBe 100d - verify(aMock).barDouble(1d) + when(aMock.barDouble(any)) thenReturn 100d + aMock.barDouble(1d) shouldBe 100d + verify(aMock).barDouble(1d) - when(aMock.barInt(any)) thenReturn 100 - aMock.barInt(1) shouldBe 100 - verify(aMock).barInt(1) + when(aMock.barInt(any)) thenReturn 100 + aMock.barInt(1) shouldBe 100 + verify(aMock).barInt(1) - when(aMock.barFloat(any)) thenReturn 100f - aMock.barFloat(1) shouldBe 100f - verify(aMock).barFloat(1) + when(aMock.barFloat(any)) thenReturn 100f + aMock.barFloat(1) shouldBe 100f + verify(aMock).barFloat(1) - when(aMock.barShort(any)) thenReturn 100.toShort - aMock.barShort(1) shouldBe 100 - verify(aMock).barShort(1) + when(aMock.barShort(any)) thenReturn 100.toShort + aMock.barShort(1) shouldBe 100 + verify(aMock).barShort(1) - when(aMock.barLong(any)) thenReturn 100l - aMock.barLong(1) shouldBe 100l - verify(aMock).barLong(1l) - } + when(aMock.barLong(any)) thenReturn 100l + aMock.barLong(1) shouldBe 100l + verify(aMock).barLong(1l) + } - "anyPrimitive" should "work with AnyVal" in { - val aMock = mock[Foo] + "anyPrimitive" should "work with AnyVal" in { + val aMock = mock[Foo] - when(aMock.barByte(anyByte)) thenReturn 10.toByte - aMock.barByte(1) shouldBe 10 - verify(aMock).barByte(1) + when(aMock.barByte(anyByte)) thenReturn 10.toByte + aMock.barByte(1) shouldBe 10 + verify(aMock).barByte(1) - when(aMock.barBoolean(anyBoolean)) thenReturn true - aMock.barBoolean(false) shouldBe true - verify(aMock).barBoolean(false) + when(aMock.barBoolean(anyBoolean)) thenReturn true + aMock.barBoolean(false) shouldBe true + verify(aMock).barBoolean(false) - when(aMock.barChar(anyChar)) thenReturn 'c' - aMock.barChar('a') shouldBe 'c' - verify(aMock).barChar('a') + when(aMock.barChar(anyChar)) thenReturn 'c' + aMock.barChar('a') shouldBe 'c' + verify(aMock).barChar('a') - when(aMock.barDouble(anyDouble)) thenReturn 100d - aMock.barDouble(1d) shouldBe 100d - verify(aMock).barDouble(1d) + when(aMock.barDouble(anyDouble)) thenReturn 100d + aMock.barDouble(1d) shouldBe 100d + verify(aMock).barDouble(1d) - when(aMock.barInt(anyInt)) thenReturn 100 - aMock.barInt(1) shouldBe 100 - verify(aMock).barInt(1) + when(aMock.barInt(anyInt)) thenReturn 100 + aMock.barInt(1) shouldBe 100 + verify(aMock).barInt(1) - when(aMock.barFloat(anyFloat)) thenReturn 100f - aMock.barFloat(1) shouldBe 100f - verify(aMock).barFloat(1) + when(aMock.barFloat(anyFloat)) thenReturn 100f + aMock.barFloat(1) shouldBe 100f + verify(aMock).barFloat(1) - when(aMock.barShort(anyShort)) thenReturn 100.toShort - aMock.barShort(1) shouldBe 100 - verify(aMock).barShort(1) + when(aMock.barShort(anyShort)) thenReturn 100.toShort + aMock.barShort(1) shouldBe 100 + verify(aMock).barShort(1) - when(aMock.barLong(anyLong)) thenReturn 100l - aMock.barLong(1) shouldBe 100l - verify(aMock).barLong(1l) - } + when(aMock.barLong(anyLong)) thenReturn 100l + aMock.barLong(1) shouldBe 100l + verify(aMock).barLong(1l) + } } diff --git a/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala index d47b7406..274dc4e6 100644 --- a/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala +++ b/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala @@ -1,142 +1,140 @@ package org.mockito.matchers import org.mockito.MockitoSugar -import org.scalatest.{FlatSpec, Matchers => ScalaTestMatchers} +import org.scalatest.{ FlatSpec, Matchers => ScalaTestMatchers } class EqMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers with EqMatchers { - case class Baz(param1: String, param2: String) + case class Baz(param1: String, param2: String) - class Foo { - def bar[T](v: T): T = v + class Foo { + def bar[T](v: T): T = v - def barTyped(v: String): String = v + def barTyped(v: String): String = v + def barByte(v: Byte): Byte = v - def barByte(v: Byte): Byte = v + def barBoolean(v: Boolean): Boolean = v - def barBoolean(v: Boolean): Boolean = v + def barChar(v: Char): Char = v - def barChar(v: Char): Char = v + def barDouble(v: Double): Double = v - def barDouble(v: Double): Double = v + def barInt(v: Int): Int = v - def barInt(v: Int): Int = v + def barFloat(v: Float): Float = v - def barFloat(v: Float): Float = v + def barShort(v: Short): Short = v - def barShort(v: Short): Short = v + def barLong(v: Long): Long = v - def barLong(v: Long): Long = v + def baz(v: Baz): Baz = v + } + "eqTo[T]" should "work with AnyRef" in { + val aMock = mock[Foo] - def baz(v: Baz): Baz = v - } + aMock.bar("meh") + verify(aMock).bar(eqTo("meh")) - "eqTo[T]" should "work with AnyRef" in { - val aMock = mock[Foo] + aMock.barTyped("meh") + verify(aMock).barTyped(eqTo("meh")) - aMock.bar("meh") - verify(aMock).bar(eqTo("meh")) + aMock.bar(Seq("meh")) + verify(aMock).bar(eqTo(Seq("meh"))) - aMock.barTyped("meh") - verify(aMock).barTyped(eqTo("meh")) + aMock.baz(Baz("Hello", "World")) + verify(aMock).baz(eqTo(Baz("Hello", "World"))) + } - aMock.bar(Seq("meh")) - verify(aMock).bar(eqTo(Seq("meh"))) + "eqTo[T]" should "work with AnyVal" in { + val aMock = mock[Foo] - aMock.baz(Baz("Hello", "World")) - verify(aMock).baz(eqTo(Baz("Hello", "World"))) - } + aMock.barByte(1) + verify(aMock).barByte(eqTo(1)) - "eqTo[T]" should "work with AnyVal" in { - val aMock = mock[Foo] + aMock.barBoolean(false) + verify(aMock).barBoolean(eqTo(false)) - aMock.barByte(1) - verify(aMock).barByte(eqTo(1)) + aMock.barChar('a') + verify(aMock).barChar(eqTo('a')) - aMock.barBoolean(false) - verify(aMock).barBoolean(eqTo(false)) + aMock.barDouble(1d) + verify(aMock).barDouble(eqTo(1d)) - aMock.barChar('a') - verify(aMock).barChar(eqTo('a')) + aMock.barInt(1) + verify(aMock).barInt(eqTo(1)) - aMock.barDouble(1d) - verify(aMock).barDouble(eqTo(1d)) + aMock.barFloat(1) + verify(aMock).barFloat(eqTo(1)) - aMock.barInt(1) - verify(aMock).barInt(eqTo(1)) + aMock.barShort(1) + verify(aMock).barShort(eqTo(1)) - aMock.barFloat(1) - verify(aMock).barFloat(eqTo(1)) + aMock.barLong(1) + verify(aMock).barLong(eqTo(1l)) + } - aMock.barShort(1) - verify(aMock).barShort(eqTo(1)) + "same[T]" should "work with AnyRef" in { + val aMock = mock[Foo] - aMock.barLong(1) - verify(aMock).barLong(eqTo(1l)) - } + aMock.bar("meh") + verify(aMock).bar(same("meh")) - "same[T]" should "work with AnyRef" in { - val aMock = mock[Foo] + aMock.barTyped("meh") + verify(aMock).barTyped(same("meh")) - aMock.bar("meh") - verify(aMock).bar(same("meh")) + val seq = Seq("meh") + aMock.bar(seq) + verify(aMock).bar(same(seq)) + } - aMock.barTyped("meh") - verify(aMock).barTyped(same("meh")) + "isA[T]" should "work with AnyRef" in { + val aMock = mock[Foo] - val seq = Seq("meh") - aMock.bar(seq) - verify(aMock).bar(same(seq)) - } + aMock.bar("meh") + verify(aMock).bar(isA[String]) - "isA[T]" should "work with AnyRef" in { - val aMock = mock[Foo] + aMock.barTyped("meh") + verify(aMock).barTyped(isA[String]) - aMock.bar("meh") - verify(aMock).bar(isA[String]) + aMock.bar(Seq("meh")) + verify(aMock).bar(isA[Seq[String]]) + } - aMock.barTyped("meh") - verify(aMock).barTyped(isA[String]) + "isA[T]" should "work with AnyVal" in { + val aMock = mock[Foo] - aMock.bar(Seq("meh")) - verify(aMock).bar(isA[Seq[String]]) - } + aMock.barByte(1) + verify(aMock).barByte(isA[Byte]) - "isA[T]" should "work with AnyVal" in { - val aMock = mock[Foo] + aMock.barBoolean(false) + verify(aMock).barBoolean(isA[Boolean]) - aMock.barByte(1) - verify(aMock).barByte(isA[Byte]) + aMock.barChar('a') + verify(aMock).barChar(isA[Char]) - aMock.barBoolean(false) - verify(aMock).barBoolean(isA[Boolean]) + aMock.barDouble(1d) + verify(aMock).barDouble(isA[Double]) - aMock.barChar('a') - verify(aMock).barChar(isA[Char]) + aMock.barInt(1) + verify(aMock).barInt(isA[Int]) - aMock.barDouble(1d) - verify(aMock).barDouble(isA[Double]) + aMock.barFloat(1) + verify(aMock).barFloat(isA[Float]) - aMock.barInt(1) - verify(aMock).barInt(isA[Int]) + aMock.barShort(1) + verify(aMock).barShort(isA[Short]) - aMock.barFloat(1) - verify(aMock).barFloat(isA[Float]) + aMock.barLong(1) + verify(aMock).barLong(isA[Long]) + } - aMock.barShort(1) - verify(aMock).barShort(isA[Short]) + "refEq[T]" should "work on scala types" in { + val aMock = mock[Foo] - aMock.barLong(1) - verify(aMock).barLong(isA[Long]) - } - - "refEq[T]" should "work on scala types" in { - val aMock = mock[Foo] - - aMock.baz(Baz("Hello", "World")) - verify(aMock).baz(refEq(Baz("Hello", "World"))) - verify(aMock).baz(refEq(Baz("Hello", "Mars"), "param2")) - } + aMock.baz(Baz("Hello", "World")) + verify(aMock).baz(refEq(Baz("Hello", "World"))) + verify(aMock).baz(refEq(Baz("Hello", "Mars"), "param2")) + } } diff --git a/core/src/test/scala/org/mockito/matchers/ThatMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/ThatMatchersTest.scala index 85270b8a..28d87437 100644 --- a/core/src/test/scala/org/mockito/matchers/ThatMatchersTest.scala +++ b/core/src/test/scala/org/mockito/matchers/ThatMatchersTest.scala @@ -1,112 +1,109 @@ package org.mockito.matchers -import org.mockito.{ArgumentMatcher, MockitoSugar} -import org.scalatest.{FlatSpec, Matchers => ScalaTestMatchers} +import org.mockito.{ ArgumentMatcher, MockitoSugar } +import org.scalatest.{ FlatSpec, Matchers => ScalaTestMatchers } class ThatMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers with ThatMatchers { - class EqTo[T](value: T) extends ArgumentMatcher[T] { - override def matches(argument: T): Boolean = argument == value - } + class EqTo[T](value: T) extends ArgumentMatcher[T] { + override def matches(argument: T): Boolean = argument == value + } + case class Baz(param1: String, param2: String) - case class Baz(param1: String, param2: String) + class Foo { + def bar[T](v: T): T = v - class Foo { - def bar[T](v: T): T = v + def barTyped(v: String): String = v - def barTyped(v: String): String = v + def barByte(v: Byte): Byte = v + def barBoolean(v: Boolean): Boolean = v - def barByte(v: Byte): Byte = v + def barChar(v: Char): Char = v - def barBoolean(v: Boolean): Boolean = v + def barDouble(v: Double): Double = v - def barChar(v: Char): Char = v + def barInt(v: Int): Int = v - def barDouble(v: Double): Double = v + def barFloat(v: Float): Float = v - def barInt(v: Int): Int = v + def barShort(v: Short): Short = v - def barFloat(v: Float): Float = v + def barLong(v: Long): Long = v - def barShort(v: Short): Short = v + def baz(v: Baz): Baz = v + } - def barLong(v: Long): Long = v + "argThat[T]" should "work with AnyRef" in { + val aMock = mock[Foo] + aMock.bar("meh") + verify(aMock).bar(argThat(new EqTo("meh"))) - def baz(v: Baz): Baz = v - } + aMock.barTyped("meh") + verify(aMock).barTyped(argThat(new EqTo("meh"))) - "argThat[T]" should "work with AnyRef" in { - val aMock = mock[Foo] + aMock.bar(Seq("meh")) + verify(aMock).bar(argThat(new EqTo(Seq("meh")))) - aMock.bar("meh") - verify(aMock).bar(argThat(new EqTo("meh"))) + aMock.baz(Baz("Hello", "World")) + verify(aMock).baz(argThat(new EqTo(Baz("Hello", "World")))) + } - aMock.barTyped("meh") - verify(aMock).barTyped(argThat(new EqTo("meh"))) + "argThat[T]" should "work with AnyVal" in { + val aMock = mock[Foo] - aMock.bar(Seq("meh")) - verify(aMock).bar(argThat(new EqTo(Seq("meh")))) + aMock.barByte(1) + verify(aMock).barByte(argThat(new EqTo(1.toByte))) - aMock.baz(Baz("Hello", "World")) - verify(aMock).baz(argThat(new EqTo(Baz("Hello", "World")))) - } + aMock.barBoolean(false) + verify(aMock).barBoolean(argThat(new EqTo(false))) - "argThat[T]" should "work with AnyVal" in { - val aMock = mock[Foo] + aMock.barChar('a') + verify(aMock).barChar(argThat(new EqTo('a'))) - aMock.barByte(1) - verify(aMock).barByte(argThat(new EqTo(1.toByte))) + aMock.barDouble(1d) + verify(aMock).barDouble(argThat(new EqTo(1d))) - aMock.barBoolean(false) - verify(aMock).barBoolean(argThat(new EqTo(false))) + aMock.barInt(1) + verify(aMock).barInt(argThat(new EqTo(1))) - aMock.barChar('a') - verify(aMock).barChar(argThat(new EqTo('a'))) + aMock.barFloat(1) + verify(aMock).barFloat(argThat(new EqTo(1))) - aMock.barDouble(1d) - verify(aMock).barDouble(argThat(new EqTo(1d))) + aMock.barShort(1) + verify(aMock).barShort(argThat(new EqTo(1.toShort))) - aMock.barInt(1) - verify(aMock).barInt(argThat(new EqTo(1))) + aMock.barLong(1) + verify(aMock).barLong(argThat(new EqTo(1l))) + } - aMock.barFloat(1) - verify(aMock).barFloat(argThat(new EqTo(1))) + "primitiveThat[T]" should "work with AnyVal" in { + val aMock = mock[Foo] - aMock.barShort(1) - verify(aMock).barShort(argThat(new EqTo(1.toShort))) + aMock.barByte(1) + verify(aMock).barByte(byteThat(new EqTo(1.toByte))) - aMock.barLong(1) - verify(aMock).barLong(argThat(new EqTo(1l))) - } + aMock.barBoolean(false) + verify(aMock).barBoolean(booleanThat(new EqTo(false))) - "primitiveThat[T]" should "work with AnyVal" in { - val aMock = mock[Foo] + aMock.barChar('a') + verify(aMock).barChar(charThat(new EqTo('a'))) - aMock.barByte(1) - verify(aMock).barByte(byteThat(new EqTo(1.toByte))) + aMock.barDouble(1d) + verify(aMock).barDouble(doubleThat(new EqTo(1d))) - aMock.barBoolean(false) - verify(aMock).barBoolean(booleanThat(new EqTo(false))) + aMock.barInt(1) + verify(aMock).barInt(intThat(new EqTo(1))) - aMock.barChar('a') - verify(aMock).barChar(charThat(new EqTo('a'))) + aMock.barFloat(1) + verify(aMock).barFloat(floatThat(new EqTo(1))) - aMock.barDouble(1d) - verify(aMock).barDouble(doubleThat(new EqTo(1d))) + aMock.barShort(1) + verify(aMock).barShort(shortThat(new EqTo(1.toShort))) - aMock.barInt(1) - verify(aMock).barInt(intThat(new EqTo(1))) - - aMock.barFloat(1) - verify(aMock).barFloat(floatThat(new EqTo(1))) - - aMock.barShort(1) - verify(aMock).barShort(shortThat(new EqTo(1.toShort))) - - aMock.barLong(1) - verify(aMock).barLong(longThat(new EqTo(1l))) - } + aMock.barLong(1) + verify(aMock).barLong(longThat(new EqTo(1l))) + } } diff --git a/gradle/shipkit.gradle b/gradle/shipkit.gradle index b216ef2c..67727bad 100644 --- a/gradle/shipkit.gradle +++ b/gradle/shipkit.gradle @@ -23,12 +23,12 @@ allprojects { userOrg = 'mockito' licenses = ['MIT'] labels = ['mocks', 'tdd', 'unit tests'] - publish = true //can be changed to 'false' for testing + publish = true //can be changed to 'false' for testing filesSpec { - from releaseSpec - into '.' - } + from releaseSpec + into '.' + } version { mavenCentralSync { diff --git a/project/build.properties b/project/build.properties index 16eecf57..bf245472 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version = 1.1.6 \ No newline at end of file +sbt.version=1.1.6 \ No newline at end of file From c9ded2690e635a5d6f0d767df98b063f0e9339bf Mon Sep 17 00:00:00 2001 From: Bruno Bonanno <241804+bbonanno@users.noreply.github.com> Date: Wed, 1 Aug 2018 18:49:22 +0100 Subject: [PATCH 3/7] anyVal working --- build.sbt | 1 + .../org/mockito/matchers/AnyMatchers.scala | 19 +++++---- .../mockito/matchers/AnyMatchersTest.scala | 35 ++++++++++++++--- .../org/mockito/ValueClassMatchers.scala | 39 +++++++++++++++++++ 4 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 macro/src/main/scala/org/mockito/ValueClassMatchers.scala diff --git a/build.sbt b/build.sbt index f3e0fea4..84187d1e 100644 --- a/build.sbt +++ b/build.sbt @@ -64,6 +64,7 @@ lazy val macroSub = (project in file("macro")) .settings( commonSettings, libraryDependencies += scalaReflect.value, + libraryDependencies += "org.mockito" % "mockito-core" % "2.19.0", publish := {}, publishLocal := {} ) diff --git a/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala b/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala index faef301b..270cfaf5 100644 --- a/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala @@ -11,7 +11,7 @@ package org.mockito.matchers -import org.mockito.{ArgumentMatchers => JavaMatchers} +import org.mockito.{ ValueClassMatchers, ArgumentMatchers => JavaMatchers } private[mockito] trait AnyMatchers { @@ -77,12 +77,17 @@ private[mockito] trait AnyMatchers { */ def any[T]: T = JavaMatchers.any[T]() - /** - * Delegates to ArgumentMatchers.anyByte(), it's only here so we expose all the `ArgumentMatchers` - * on a single place as any[T] would do the job just fine - * - */ - def anyByte: Byte = JavaMatchers.anyByte + /** + * Wraps the standard 'any' matcher on the value class provided, this one requires the type to be explicit + */ + def anyVal[T](implicit valueClassMatchers: ValueClassMatchers[T]): T = valueClassMatchers.anyVal + + /** + * Delegates to ArgumentMatchers.anyByte(), it's only here so we expose all the `ArgumentMatchers` + * on a single place as any[T] would do the job just fine + * + */ + def anyByte: Byte = JavaMatchers.anyByte /** * Delegates to ArgumentMatchers.anyBoolean(), it's only here so we expose all the `ArgumentMatchers` diff --git a/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala index 2e0e7609..fd32cb6e 100644 --- a/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala +++ b/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala @@ -1,9 +1,12 @@ package org.mockito.matchers import org.mockito.MockitoSugar -import org.scalatest.{FlatSpec, Matchers => ScalaTestMatchers} +import org.mockito.matchers.AnyMatchersTest._ +import org.scalatest.{ FlatSpec, Matchers => ScalaTestMatchers } -class AnyMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers with AnyMatchers { +object AnyMatchersTest { + class ValueClass(val v: String) extends AnyVal + case class ValueCaseClass(v: Int) extends AnyVal class Foo { def bar[T](v: T): T = v @@ -34,8 +37,16 @@ class AnyMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers def barMap[K, V](v: Map[K, V]): Map[K, V] = v - def barSet[T](v: Set[T]): Set[T] = v - } + def barSet[T](v: Set[T]): Set[T] = v + + def valueClass(v: ValueClass): String = v.v + + def valueCaseClass(v: ValueCaseClass): Int = v.v + } + +} + +class AnyMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers with AnyMatchers { "any[Collection]" should "work with Scala types" in { val aMock = mock[Foo] @@ -75,8 +86,20 @@ class AnyMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers verify(aMock).barTyped("meh") } - "any" should "work with AnyVal" in { - val aMock = mock[Foo] + "anyVal" should "work with a value class" in { + val aMock = mock[Foo] + + when(aMock.valueClass(anyVal[ValueClass])) thenReturn "mocked!" + aMock.valueClass(new ValueClass("meh")) shouldBe "mocked!" + verify(aMock).valueClass(new ValueClass("meh")) + + when(aMock.valueCaseClass(anyVal[ValueCaseClass])) thenReturn 100 + aMock.valueCaseClass(ValueCaseClass(1)) shouldBe 100 + verify(aMock).valueCaseClass(ValueCaseClass(1)) + } + + "any" should "work with AnyVal" in { + val aMock = mock[Foo] when(aMock.barByte(any)) thenReturn 10.toByte aMock.barByte(1) shouldBe 10 diff --git a/macro/src/main/scala/org/mockito/ValueClassMatchers.scala b/macro/src/main/scala/org/mockito/ValueClassMatchers.scala new file mode 100644 index 00000000..b66bd995 --- /dev/null +++ b/macro/src/main/scala/org/mockito/ValueClassMatchers.scala @@ -0,0 +1,39 @@ +package org.mockito + +import scala.language.experimental.macros +import scala.reflect.macros.whitebox + +trait ValueClassMatchers[T] { + + def anyVal: T + +} + +object ValueClassMatchers { + + implicit def materializeValueClassMatchers[T]: ValueClassMatchers[T] = macro materializeValueClassMatchersMacro[T] + + def materializeValueClassMatchersMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[ValueClassMatchers[T]] = { + import c.universe._ + val tpe = weakTypeOf[T] + + val param = tpe.decls + .collectFirst { + case m: MethodSymbol if m.isPrimaryConstructor ⇒ m + } + .get + .paramLists + .head + .head + + val paramType = tpe.decl(param.name).typeSignature.finalResultType + + val r = c.Expr[ValueClassMatchers[T]] { q""" + new org.mockito.ValueClassMatchers[$tpe] { + override def anyVal: $tpe = new $tpe(org.mockito.ArgumentMatchers.any[$paramType]()) + } + """ } + println(show(r)) + r + } +} From f5931a587c01862af92d5c2a2b574ff11914f925 Mon Sep 17 00:00:00 2001 From: Bruno Bonanno <241804+bbonanno@users.noreply.github.com> Date: Wed, 1 Aug 2018 19:14:48 +0100 Subject: [PATCH 4/7] eqToVal working --- .../scala/org/mockito/matchers/EqMatchers.scala | 13 ++++++++----- .../org/mockito/matchers/AnyMatchersTest.scala | 9 +-------- .../org/mockito/matchers/EqMatchersTest.scala | 14 ++++++++++++++ .../test/scala/org/mockito/matchers/package.scala | 6 ++++++ .../scala/org/mockito/ValueClassMatchers.scala | 7 ++++--- 5 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 core/src/test/scala/org/mockito/matchers/package.scala diff --git a/core/src/main/scala/org/mockito/matchers/EqMatchers.scala b/core/src/main/scala/org/mockito/matchers/EqMatchers.scala index d09082d4..689efacb 100644 --- a/core/src/main/scala/org/mockito/matchers/EqMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/EqMatchers.scala @@ -11,7 +11,7 @@ package org.mockito.matchers -import org.mockito.{ ArgumentMatchers => JavaMatchers } +import org.mockito.{ ValueClassMatchers, ArgumentMatchers => JavaMatchers } import scala.reflect.ClassTag @@ -24,6 +24,11 @@ private[mockito] trait EqMatchers { */ def eqTo[T](value: T): T = JavaMatchers.eq(value) + /** + * Wraps the standard 'ArgumentMatchers.eq()' matcher on the value class provided, this one requires the type to be explicit + */ + def eqToVal[T](value: Any)(implicit valueClassMatchers: ValueClassMatchers[T]): T = valueClassMatchers.eqToVal(value) + /** * Delegates to ArgumentMatchers.same(), it's only here so we expose all the `ArgumentMatchers` * on a single place @@ -36,14 +41,12 @@ private[mockito] trait EqMatchers { * It provides a nicer API as you can, for instance, do isA[String] instead of isA(classOf[String]) * */ - def isA[T](implicit classTag: ClassTag[T]): T = - JavaMatchers.isA(classTag.runtimeClass.asInstanceOf[Class[T]]) + def isA[T](implicit classTag: ClassTag[T]): T = JavaMatchers.isA(classTag.runtimeClass.asInstanceOf[Class[T]]) /** * Delegates to ArgumentMatchers.refEq(), it's only here so we expose all the `ArgumentMatchers` * on a single place * */ - def refEq[T](value: T, excludeFields: String*): T = - JavaMatchers.refEq(value, excludeFields: _*) + def refEq[T](value: T, excludeFields: String*): T = JavaMatchers.refEq(value, excludeFields: _*) } diff --git a/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala index fd32cb6e..a91743e2 100644 --- a/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala +++ b/core/src/test/scala/org/mockito/matchers/AnyMatchersTest.scala @@ -1,12 +1,9 @@ package org.mockito.matchers import org.mockito.MockitoSugar -import org.mockito.matchers.AnyMatchersTest._ import org.scalatest.{ FlatSpec, Matchers => ScalaTestMatchers } -object AnyMatchersTest { - class ValueClass(val v: String) extends AnyVal - case class ValueCaseClass(v: Int) extends AnyVal +class AnyMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers with AnyMatchers { class Foo { def bar[T](v: T): T = v @@ -44,10 +41,6 @@ object AnyMatchersTest { def valueCaseClass(v: ValueCaseClass): Int = v.v } -} - -class AnyMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers with AnyMatchers { - "any[Collection]" should "work with Scala types" in { val aMock = mock[Foo] diff --git a/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala b/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala index 274dc4e6..93f8ab72 100644 --- a/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala +++ b/core/src/test/scala/org/mockito/matchers/EqMatchersTest.scala @@ -29,6 +29,20 @@ class EqMatchersTest extends FlatSpec with MockitoSugar with ScalaTestMatchers w def barLong(v: Long): Long = v def baz(v: Baz): Baz = v + + def valueClass(v: ValueClass): String = v.v + + def valueCaseClass(v: ValueCaseClass): Int = v.v + } + + "eqToVal[T]" should "work with value classes" in { + val aMock = mock[Foo] + + aMock.valueClass(new ValueClass("meh")) + verify(aMock).valueClass(eqToVal[ValueClass]("meh")) + + aMock.valueCaseClass(ValueCaseClass(100)) + verify(aMock).valueCaseClass(eqToVal[ValueCaseClass](100)) } "eqTo[T]" should "work with AnyRef" in { diff --git a/core/src/test/scala/org/mockito/matchers/package.scala b/core/src/test/scala/org/mockito/matchers/package.scala new file mode 100644 index 00000000..8d7c8adb --- /dev/null +++ b/core/src/test/scala/org/mockito/matchers/package.scala @@ -0,0 +1,6 @@ +package org.mockito + +package object matchers { + class ValueClass(val v: String) extends AnyVal + case class ValueCaseClass(v: Int) extends AnyVal +} diff --git a/macro/src/main/scala/org/mockito/ValueClassMatchers.scala b/macro/src/main/scala/org/mockito/ValueClassMatchers.scala index b66bd995..ace9da24 100644 --- a/macro/src/main/scala/org/mockito/ValueClassMatchers.scala +++ b/macro/src/main/scala/org/mockito/ValueClassMatchers.scala @@ -7,6 +7,8 @@ trait ValueClassMatchers[T] { def anyVal: T + def eqToVal(v: Any): T + } object ValueClassMatchers { @@ -28,12 +30,11 @@ object ValueClassMatchers { val paramType = tpe.decl(param.name).typeSignature.finalResultType - val r = c.Expr[ValueClassMatchers[T]] { q""" + c.Expr[ValueClassMatchers[T]] { q""" new org.mockito.ValueClassMatchers[$tpe] { override def anyVal: $tpe = new $tpe(org.mockito.ArgumentMatchers.any[$paramType]()) + override def eqToVal(v: Any): $tpe = new $tpe(org.mockito.ArgumentMatchers.eq[$paramType](v.asInstanceOf[$paramType])) } """ } - println(show(r)) - r } } From f2ba40d1d1f6dc2388ffa84702169a7c3f5dfb55 Mon Sep 17 00:00:00 2001 From: Bruno Bonanno <241804+bbonanno@users.noreply.github.com> Date: Wed, 1 Aug 2018 19:19:41 +0100 Subject: [PATCH 5/7] tidy up sbt --- build.sbt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/build.sbt b/build.sbt index 84187d1e..8252b4be 100644 --- a/build.sbt +++ b/build.sbt @@ -4,9 +4,11 @@ import scala.io.Source import scala.language.postfixOps import scala.util.Try +val _scalaVersion = "2.12.6" + lazy val commonSettings = Seq( - scalaVersion := "2.12.6", + scalaVersion := _scalaVersion, organization := "org.mockito", //Load version from the file so that Gradle/Shipkit and SBT use the same version version := { @@ -20,18 +22,18 @@ lazy val commonSettings = } ) -lazy val scalaReflect = Def.setting { - "org.scala-lang" % "scala-reflect" % scalaVersion.value -} +lazy val commonLibraries = Seq( + "org.mockito" % "mockito-core" % "2.19.0", + "org.scala-lang" % "scala-reflect" % _scalaVersion +) lazy val core = (project in file("core")) .dependsOn(macroSub % "compile-internal, test-internal") .settings( commonSettings, name := "mockito-scala", + libraryDependencies ++= commonLibraries, libraryDependencies ++= Seq( - "org.mockito" % "mockito-core" % "2.19.0", - scalaReflect.value, "org.scalatest" %% "scalatest" % "3.0.5" % Test ), // include the macro classes and resources in the main jar @@ -63,8 +65,7 @@ lazy val core = (project in file("core")) lazy val macroSub = (project in file("macro")) .settings( commonSettings, - libraryDependencies += scalaReflect.value, - libraryDependencies += "org.mockito" % "mockito-core" % "2.19.0", + libraryDependencies ++= commonLibraries, publish := {}, publishLocal := {} ) From 0536b0a0e95f170936b24714efbcb08a6f4227e0 Mon Sep 17 00:00:00 2001 From: Bruno Bonanno <241804+bbonanno@users.noreply.github.com> Date: Wed, 1 Aug 2018 19:40:58 +0100 Subject: [PATCH 6/7] Add readme section for value class matchers --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 4d318cea..2e2ee04b 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,22 @@ This trait exposes all the existent `org.mockito.ArgumentMatchers` but again it * `eq` was renamed to `eqTo` to avoid clashing with the Scala `eq` operator for identity equality * `any` resolves to the correct type most of the times, removing the need of using the likes of `anyString`, `anyInt`, etc * `isNull` and `isNotNull` are deprecated as using nulls in Scala is clear code smell +* Adds support for value classes via `anyVal[T]` and `eqToVal[T]()` Again, the companion object also extends the trait to allow the usage of the API without mixing-in the trait in case that's desired +### Value Class Matchers + +The matchers for the value classes always require the type to be explicit, apart from that, they should be used as any other matcher, e.g. + ``` + when(myObj.myMethod(any[MyValueClass]) thenReturn "something" + + myObj.myMethod(MyValueClass(456)) shouldBe "something" + + verify(myObj).myMethod(eqToVal[MyValueClass](456)) + ``` + + ## Authors * **Bruno Bonanno** - *Initial work* - [bbonanno](https://github.com/bbonanno) From 19f3924c6785ff043c312655c15c69fb1b8db040 Mon Sep 17 00:00:00 2001 From: Bruno Bonanno <241804+bbonanno@users.noreply.github.com> Date: Wed, 1 Aug 2018 19:49:31 +0100 Subject: [PATCH 7/7] Move ValueClassMatchers to the matchers package --- core/src/main/scala/org/mockito/matchers/AnyMatchers.scala | 2 +- core/src/main/scala/org/mockito/matchers/EqMatchers.scala | 2 +- .../scala/org/mockito/{ => matchers}/ValueClassMatchers.scala | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename macro/src/main/scala/org/mockito/{ => matchers}/ValueClassMatchers.scala (92%) diff --git a/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala b/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala index 270cfaf5..14b2d9b0 100644 --- a/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/AnyMatchers.scala @@ -11,7 +11,7 @@ package org.mockito.matchers -import org.mockito.{ ValueClassMatchers, ArgumentMatchers => JavaMatchers } +import org.mockito.{ ArgumentMatchers => JavaMatchers } private[mockito] trait AnyMatchers { diff --git a/core/src/main/scala/org/mockito/matchers/EqMatchers.scala b/core/src/main/scala/org/mockito/matchers/EqMatchers.scala index 689efacb..1d28a6a1 100644 --- a/core/src/main/scala/org/mockito/matchers/EqMatchers.scala +++ b/core/src/main/scala/org/mockito/matchers/EqMatchers.scala @@ -11,7 +11,7 @@ package org.mockito.matchers -import org.mockito.{ ValueClassMatchers, ArgumentMatchers => JavaMatchers } +import org.mockito.{ ArgumentMatchers => JavaMatchers } import scala.reflect.ClassTag diff --git a/macro/src/main/scala/org/mockito/ValueClassMatchers.scala b/macro/src/main/scala/org/mockito/matchers/ValueClassMatchers.scala similarity index 92% rename from macro/src/main/scala/org/mockito/ValueClassMatchers.scala rename to macro/src/main/scala/org/mockito/matchers/ValueClassMatchers.scala index ace9da24..cc350854 100644 --- a/macro/src/main/scala/org/mockito/ValueClassMatchers.scala +++ b/macro/src/main/scala/org/mockito/matchers/ValueClassMatchers.scala @@ -1,4 +1,4 @@ -package org.mockito +package org.mockito.matchers import scala.language.experimental.macros import scala.reflect.macros.whitebox @@ -31,7 +31,7 @@ object ValueClassMatchers { val paramType = tpe.decl(param.name).typeSignature.finalResultType c.Expr[ValueClassMatchers[T]] { q""" - new org.mockito.ValueClassMatchers[$tpe] { + new org.mockito.matchers.ValueClassMatchers[$tpe] { override def anyVal: $tpe = new $tpe(org.mockito.ArgumentMatchers.any[$paramType]()) override def eqToVal(v: Any): $tpe = new $tpe(org.mockito.ArgumentMatchers.eq[$paramType](v.asInstanceOf[$paramType])) }