diff --git a/.bsp/sbt.json b/.bsp/sbt.json deleted file mode 100644 index 0143c11d..00000000 --- a/.bsp/sbt.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"sbt","version":"1.6.2","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/bin/java","-Xms100m","-Xmx100m","-classpath","/usr/local/Cellar/sbt/1.6.2/libexec/bin/sbt-launch.jar","-Dsbt.script=/usr/local/Cellar/sbt/1.6.2/libexec/bin/sbt","xsbt.boot.Boot","-bsp"]} \ No newline at end of file diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 839a4891..6c5fb9a1 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - jdk: [ 8, 11, 17 ] + jdk: [ 11, 17 ] runs-on: ubuntu-latest env: @@ -53,7 +53,7 @@ jobs: strategy: fail-fast: false matrix: - jdk: [ 8, 11, 17] + jdk: [ 11, 17] runs-on: ubuntu-latest env: diff --git a/.gitignore b/.gitignore index a0228539..3fc8d32c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,13 @@ dist /.settings /.target /.cache -*.DS_Store \ No newline at end of file +*.DS_Store + +# Metals +.metals/* +.bloop/* +.vscode/* +**/.bloop/* +**/metals.sbt + +.bsp/* diff --git a/build.sbt b/build.sbt index 5f584953..acc1a469 100644 --- a/build.sbt +++ b/build.sbt @@ -2,10 +2,12 @@ import Dependencies.Library import sbt.CrossVersion lazy val repo: String = "https://s01.oss.sonatype.org" -lazy val scala213: String = "2.13.8" +lazy val scala213: String = "2.13.10" lazy val scala31: String = "3.1.2" // Ready for cross build, currently not yet supported by play. lazy val supportedScalaVersions: Seq[String] = Seq(scala213 /*, scala31*/) +Global / evictionErrorLevel := Level.Info + ThisBuild / description := "Authentication library for Play Framework applications that supports several authentication methods, including OAuth1, OAuth2, OpenID, CAS, Credentials, Basic Authentication, Two Factor Authentication or custom authentication schemes" ThisBuild / homepage := Some(url("https://silhouette.readme.io/")) ThisBuild / licenses := Seq("Apache License" -> url("https://github.com/honeycomb-cheesecake/play-silhouette/blob/master/LICENSE")) @@ -49,7 +51,7 @@ ThisBuild / publishTo := { } } ThisBuild / versionPolicyIntention := Compatibility.BinaryAndSourceCompatible -ThisBuild / scapegoatVersion := "1.4.13" +ThisBuild / scapegoatVersion := "2.1.1" dependencyCheckAssemblyAnalyzerEnabled := Some(false) dependencyCheckFormat := "ALL" @@ -101,7 +103,9 @@ lazy val silhouette = (project in file("silhouette")) .settings( name := "play-silhouette", dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"), - dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"), + dependencyUpdatesFilter -= moduleFilter(organization = "com.typesafe.akka", name = "akka-testkit"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), + dependencyUpdatesFilter -= moduleFilter(organization = "om.auth0", name = "java-jwt"), libraryDependencies ++= Library.updates ++ Seq( Library.Play.cache, @@ -111,7 +115,7 @@ lazy val silhouette = (project in file("silhouette")) Library.apacheCommonLang, Library.Play.specs2 % Test, Library.Specs2.matcherExtra % Test, - Library.Specs2.mock % Test, + Library.mockito % Test, Library.scalaGuice % Test, Library.akkaTestkit % Test ), @@ -119,20 +123,21 @@ lazy val silhouette = (project in file("silhouette")) scapegoatDisabledInspections := Seq("AsInstanceOf", "BooleanParameter", "ComparingUnrelatedTypes", "FinalModifierOnCaseClass", "MethodNames") ) .enablePlugins(PlayScala) + .disablePlugins(PlayAkkaHttpServer) lazy val silhouetteCas = (project in file("silhouette-cas")) .settings( name := "play-silhouette-cas", dependencyUpdatesFailBuild := true, dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"), - dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), libraryDependencies ++= Library.updates ++ Seq( Library.casClient, Library.casClientSupportSAML, Library.Play.specs2 % Test, Library.Specs2.matcherExtra % Test, - Library.Specs2.mock % Test, + Library.mockito % Test, Library.scalaGuice % Test ), scapegoatDisabledInspections := Seq("AsInstanceOf", "BooleanParameter", "ComparingUnrelatedTypes", "FinalModifierOnCaseClass", "MethodNames") @@ -144,6 +149,7 @@ lazy val silhouetteTotp = (project in file("silhouette-totp")) name := "play-silhouette-totp", dependencyUpdatesFailBuild := true, dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), libraryDependencies ++= Library.updates ++ Seq( Library.googleAuth, @@ -159,6 +165,9 @@ lazy val silhouetteCryptoJca = (project in file("silhouette-crypto-jca")) dependencyUpdatesFailBuild := true, dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"), dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-codec", name = "commons-codec"), + libraryDependencies ++= Library.updates ++ Seq( Library.commonsCodec, @@ -174,6 +183,7 @@ lazy val silhouetteArgon2 = (project in file("silhouette-password-argon2")) name := "play-silhouette-password-argon2", dependencyUpdatesFailBuild := true, dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), libraryDependencies ++= Library.updates ++ Seq( Library.argon2, @@ -188,6 +198,7 @@ lazy val silhouetteBcrypt = (project in file("silhouette-password-bcrypt")) name := "play-silhouette-password-bcrypt", dependencyUpdatesFailBuild := true, dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), libraryDependencies ++= Library.updates ++ Seq( Library.jbcrypt, @@ -203,12 +214,12 @@ lazy val silhouettePersistence = (project in file("silhouette-persistence")) dependencyUpdatesFailBuild := true, dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-core"), dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"), - dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), libraryDependencies ++= Library.updates ++ Seq( Library.Specs2.core % Test, Library.Specs2.matcherExtra % Test, - Library.Specs2.mock % Test, + Library.mockito % Test, Library.scalaGuice % Test ), scapegoatDisabledInspections := Seq("AsInstanceOf", "BooleanParameter", "ComparingUnrelatedTypes", "FinalModifierOnCaseClass", "MethodNames") @@ -220,13 +231,14 @@ lazy val silhouetteTestkit = (project in file("silhouette-testkit")) name := "play-silhouette-testkit", dependencyUpdatesFailBuild := true, dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-matcher-extra"), - dependencyUpdatesFilter -= moduleFilter(organization = "org.specs2", name = "specs2-mock"), + dependencyUpdatesFilter -= moduleFilter(organization = "com.typesafe.akka", name = "akka-testkit"), + dependencyUpdatesFilter -= moduleFilter(organization = "commons-io", name = "commons-io"), libraryDependencies ++= Library.updates ++ Seq( Library.Play.test, Library.Play.specs2 % Test, Library.Specs2.matcherExtra % Test, - Library.Specs2.mock % Test, + Library.mockito % Test, Library.scalaGuice % Test, Library.akkaTestkit % Test ), diff --git a/project/Dependencies.scala b/project/Dependencies.scala index a6c8d0ec..252bbd71 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -38,15 +38,15 @@ object Dependencies { private val version = "4.9.4" // Versions later than this will fail due to removed dependencies. val core = "org.specs2" %% "specs2-core" % version val matcherExtra = "org.specs2" %% "specs2-matcher-extra" % version - val mock = "org.specs2" %% "specs2-mock" % version } val argon2 = "de.mkammerer" % "argon2-jvm" % "2.11" val commonsCodec = "commons-codec" % "commons-codec" % "1.15" val jbcrypt = "de.svenkubiak" % "jBCrypt" % "0.4.3" val jwt = "com.auth0" % "java-jwt" % "3.18.2" - val scalaGuice = "net.codingwell" %% "scala-guice" % "5.1.0" + val scalaGuice = "net.codingwell" %% "scala-guice" % "5.1.1" val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % play.core.PlayVersion.akkaVersion + val mockito = "org.mockito" % "mockito-core" % "5.3.0" val casClient = "org.jasig.cas.client" % "cas-client-core" % "3.6.4" val casClientSupportSAML = "org.jasig.cas.client" % "cas-client-support-saml" % "3.6.4" val apacheCommonLang = "org.apache.commons" % "commons-lang3" % "3.12.0" diff --git a/project/plugins.sbt b/project/plugins.sbt index 0122759a..d8bbb826 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,12 +1,14 @@ -addSbtPlugin(dependency = "ch.epfl.scala" % "sbt-version-policy" % "2.0.1") +Global / evictionErrorLevel := Level.Info + +addSbtPlugin(dependency = "ch.epfl.scala" % "sbt-version-policy" % "2.1.0") addSbtPlugin(dependency = "com.github.sbt" % "sbt-release" % "1.1.0") addSbtPlugin(dependency = "com.github.sbt" % "sbt-unidoc" % "0.5.0") -addSbtPlugin(dependency = "com.jsuereth" % "sbt-pgp" % "2.0.2") +addSbtPlugin(dependency = "com.jsuereth" % "sbt-pgp" % "2.1.1") addSbtPlugin(dependency = "com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.1.1") -addSbtPlugin(dependency = "com.timushev.sbt" % "sbt-updates" % "0.6.2") -addSbtPlugin(dependency = "com.typesafe.play" % "sbt-plugin" % "2.8.16") -addSbtPlugin(dependency = "net.vonbuchholtz" % "sbt-dependency-check" % "4.0.0") -addSbtPlugin(dependency = "org.scalariform" % "sbt-scalariform" % "1.8.2") -addSbtPlugin(dependency = "org.scoverage" % "sbt-scoverage" % "1.9.3") -addSbtPlugin(dependency = "org.scoverage" % "sbt-coveralls" % "1.3.2") -addSbtPlugin(dependency = "org.xerial.sbt" % "sbt-sonatype" % "3.9.12") +addSbtPlugin(dependency = "com.timushev.sbt" % "sbt-updates" % "0.6.4") +addSbtPlugin(dependency = "com.typesafe.play" % "sbt-plugin" % "2.8.19") +addSbtPlugin(dependency = "net.vonbuchholtz" % "sbt-dependency-check" % "5.1.0") +addSbtPlugin(dependency = "org.scalariform" % "sbt-scalariform" % "1.8.3") +addSbtPlugin(dependency = "org.scoverage" % "sbt-scoverage" % "2.0.7") +addSbtPlugin(dependency = "org.scoverage" % "sbt-coveralls" % "1.3.7") +addSbtPlugin(dependency = "org.xerial.sbt" % "sbt-sonatype" % "3.9.18") diff --git a/silhouette-cas/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/CasProviderSpec.scala b/silhouette-cas/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/CasProviderSpec.scala index 196b76ba..14ba1b23 100644 --- a/silhouette-cas/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/CasProviderSpec.scala +++ b/silhouette-cas/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/CasProviderSpec.scala @@ -20,7 +20,7 @@ import io.github.honeycombcheesecake.play.silhouette.api.util.HTTPLayer import io.github.honeycombcheesecake.play.silhouette.api.{ Logger, LoginInfo } import org.jasig.cas.client.authentication.AttributePrincipal -import org.specs2.mock.Mockito +import org.mockito.Mockito._ import org.specs2.specification.Scope import play.api.test.FakeRequest import test.SocialProviderSpec @@ -32,7 +32,7 @@ import scala.concurrent.duration._ /** * Test case for the [[CasProvider]] class. */ -class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logger { +class CasProviderSpec extends SocialProviderSpec[CasInfo] with Logger { "The settings" should { "fail with a ConfigurationException if casURL is invalid" in new Context { @@ -94,9 +94,9 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg "The `retrieveProfile` method" should { "return a valid profile if the CAS client validates the ticket" in new Context { - principal.getName returns userName - principal.getAttributes returns attr - client.validateServiceTicket(ticket) returns Future.successful(principal) + when(principal.getName).thenReturn(userName) + when(principal.getAttributes).thenReturn(attr) + when(client.validateServiceTicket(ticket)).thenReturn(Future.successful(principal)) implicit val req = FakeRequest(GET, "/?ticket=%s".format(ticket)) @@ -128,8 +128,8 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg redirectURL = "https://cas-redirect/") lazy val httpLayer = { - val m = mock[HTTPLayer] - m.executionContext returns global + val m = mock(classOf[HTTPLayer]) + when(m.executionContext).thenReturn(global) m } @@ -143,7 +143,7 @@ class CasProviderSpec extends SocialProviderSpec[CasInfo] with Mockito with Logg lazy val casAuthInfo = CasInfo(ticket) - lazy val principal = mock[AttributePrincipal].smart + lazy val principal = mock(classOf[AttributePrincipal], withSettings().defaultAnswer(RETURNS_SMART_NULLS)) lazy val name = "abc123" lazy val email = "email" diff --git a/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/CacheAuthenticatorRepositorySpec.scala b/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/CacheAuthenticatorRepositorySpec.scala index df805c82..781e0f24 100644 --- a/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/CacheAuthenticatorRepositorySpec.scala +++ b/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/CacheAuthenticatorRepositorySpec.scala @@ -19,9 +19,9 @@ import io.github.honeycombcheesecake.play.silhouette.api.StorableAuthenticator import io.github.honeycombcheesecake.play.silhouette.api.util.CacheLayer import io.github.honeycombcheesecake.play.silhouette.test.WaitPatience import org.specs2.concurrent.ExecutionEnv -import org.specs2.mock.Mockito import org.specs2.mutable.Specification import org.specs2.specification.Scope +import org.mockito.Mockito._ import scala.concurrent.Future import scala.concurrent.duration.Duration @@ -29,50 +29,50 @@ import scala.concurrent.duration.Duration /** * Test case for the [[CacheAuthenticatorRepository]] class. */ -class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specification with Mockito with WaitPatience { +class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specification with WaitPatience { "The `find` method" should { "return value from cache" in new Context { - cacheLayer.find[StorableAuthenticator]("test-id") returns Future.successful(Some(authenticator)) + when(cacheLayer.find[StorableAuthenticator]("test-id")).thenReturn(Future.successful(Some(authenticator))) repository.find("test-id") must beSome(authenticator).awaitWithPatience - there was one(cacheLayer).find[StorableAuthenticator]("test-id") + verify(cacheLayer).find[StorableAuthenticator]("test-id") } "return None if value couldn't be found in cache" in new Context { - cacheLayer.find[StorableAuthenticator]("test-id") returns Future.successful(None) + when(cacheLayer.find[StorableAuthenticator]("test-id")).thenReturn(Future.successful(None)) repository.find("test-id") must beNone.awaitWithPatience - there was one(cacheLayer).find[StorableAuthenticator]("test-id") + verify(cacheLayer).find[StorableAuthenticator]("test-id") } } "The `add` method" should { "add value in cache" in new Context { - authenticator.id returns "test-id" - cacheLayer.save("test-id", authenticator, Duration.Inf) returns Future.successful(authenticator) + when(authenticator.id).thenReturn("test-id") + when(cacheLayer.save("test-id", authenticator, Duration.Inf)).thenReturn(Future.successful(authenticator)) repository.add(authenticator) must beEqualTo(authenticator).awaitWithPatience - there was one(cacheLayer).save("test-id", authenticator, Duration.Inf) + verify(cacheLayer).save("test-id", authenticator, Duration.Inf) } } "The `update` method" should { "update value in cache" in new Context { - authenticator.id returns "test-id" - cacheLayer.save("test-id", authenticator, Duration.Inf) returns Future.successful(authenticator) + when(authenticator.id).thenReturn("test-id") + when(cacheLayer.save("test-id", authenticator, Duration.Inf)).thenReturn(Future.successful(authenticator)) repository.update(authenticator) must beEqualTo(authenticator).awaitWithPatience - there was one(cacheLayer).save("test-id", authenticator, Duration.Inf) + verify(cacheLayer).save("test-id", authenticator, Duration.Inf) } } "The `remove` method" should { "remove value from cache" in new Context { - cacheLayer.remove("test-id") returns Future.successful(()) + when(cacheLayer.remove("test-id")).thenReturn(Future.successful(())) repository.remove("test-id") must beEqualTo(()).awaitWithPatience - there was one(cacheLayer).remove("test-id") + verify(cacheLayer).remove("test-id") } } @@ -84,12 +84,12 @@ class CacheAuthenticatorRepositorySpec(implicit ev: ExecutionEnv) extends Specif /** * A storable authenticator. */ - lazy val authenticator = mock[StorableAuthenticator] + lazy val authenticator = mock(classOf[StorableAuthenticator]) /** * The cache layer implementation. */ - lazy val cacheLayer = mock[CacheLayer] + lazy val cacheLayer = mock(classOf[CacheLayer]) /** * The repository to test. diff --git a/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/DelegableAuthInfoRepositorySpec.scala b/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/DelegableAuthInfoRepositorySpec.scala index eeefc3df..e8c75cbe 100644 --- a/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/DelegableAuthInfoRepositorySpec.scala +++ b/silhouette-persistence/src/test/scala/io/github/honeycombcheesecake/play/silhouette/persistence/repositories/DelegableAuthInfoRepositorySpec.scala @@ -27,9 +27,9 @@ import io.github.honeycombcheesecake.play.silhouette.test.WaitPatience import net.codingwell.scalaguice.ScalaModule import org.specs2.concurrent.ExecutionEnv import org.specs2.control.NoLanguageFeatures -import org.specs2.mock.Mockito import org.specs2.mutable.Specification import org.specs2.specification.Scope +import org.mockito.Mockito._ import scala.concurrent.Await import scala.concurrent.duration._ @@ -39,7 +39,7 @@ import scala.language.postfixOps * Test case for the [[DelegableAuthInfoRepository]] trait. */ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) - extends Specification with Mockito with NoLanguageFeatures with WaitPatience { + extends Specification with NoLanguageFeatures with WaitPatience { "The `find` method" should { "delegate the PasswordInfo to the correct DAO" in new Context { @@ -48,7 +48,7 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) Await.result(passwordInfoDAO.add(loginInfo, passwordInfo), 10 seconds) service.find[PasswordInfo](loginInfo) must beSome(passwordInfo).awaitWithPatience - there was one(passwordInfoDAO).find(loginInfo) + verify(passwordInfoDAO).find(loginInfo) } "delegate the OAuth1Info to the correct DAO" in new Context { @@ -57,7 +57,7 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) Await.result(oauth1InfoDAO.add(loginInfo, oauth1Info), 10 seconds) service.find[OAuth1Info](loginInfo) must beSome(oauth1Info).awaitWithPatience - there was one(oauth1InfoDAO).find(loginInfo) + verify(oauth1InfoDAO).find(loginInfo) } "delegate the OAuth2Info to the correct DAO" in new Context { @@ -66,7 +66,7 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) Await.result(oauth2InfoDAO.add(loginInfo, oauth2Info), 10 seconds) service.find[OAuth2Info](loginInfo) must beSome(oauth2Info).awaitWithPatience - there was one(oauth2InfoDAO).find(loginInfo) + verify(oauth2InfoDAO).find(loginInfo) } "throw a ConfigurationException if an unsupported type was given" in new Context { @@ -83,21 +83,21 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) val loginInfo = LoginInfo("credentials", "1") service.add(loginInfo, passwordInfo) must beEqualTo(passwordInfo).awaitWithPatience - there was one(passwordInfoDAO).add(loginInfo, passwordInfo) + verify(passwordInfoDAO).add(loginInfo, passwordInfo) } "delegate the OAuth1Info to the correct DAO" in new Context { val loginInfo = LoginInfo("credentials", "1") service.add(loginInfo, oauth1Info) must beEqualTo(oauth1Info).awaitWithPatience - there was one(oauth1InfoDAO).add(loginInfo, oauth1Info) + verify(oauth1InfoDAO).add(loginInfo, oauth1Info) } "delegate the OAuth2Info to the correct DAO" in new Context { val loginInfo = LoginInfo("credentials", "1") service.add(loginInfo, oauth2Info) must beEqualTo(oauth2Info).awaitWithPatience - there was one(oauth2InfoDAO).add(loginInfo, oauth2Info) + verify(oauth2InfoDAO).add(loginInfo, oauth2Info) } "throw a ConfigurationException if an unsupported type was given" in new Context { @@ -114,21 +114,21 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) val loginInfo = LoginInfo("credentials", "1") service.update(loginInfo, passwordInfo) must beEqualTo(passwordInfo).awaitWithPatience - there was one(passwordInfoDAO).update(loginInfo, passwordInfo) + verify(passwordInfoDAO).update(loginInfo, passwordInfo) } "delegate the OAuth1Info to the correct DAO" in new Context { val loginInfo = LoginInfo("credentials", "1") service.update(loginInfo, oauth1Info) must beEqualTo(oauth1Info).awaitWithPatience - there was one(oauth1InfoDAO).update(loginInfo, oauth1Info) + verify(oauth1InfoDAO).update(loginInfo, oauth1Info) } "delegate the OAuth2Info to the correct DAO" in new Context { val loginInfo = LoginInfo("credentials", "1") service.update(loginInfo, oauth2Info) must beEqualTo(oauth2Info).awaitWithPatience - there was one(oauth2InfoDAO).update(loginInfo, oauth2Info) + verify(oauth2InfoDAO).update(loginInfo, oauth2Info) } "throw a ConfigurationException if an unsupported type was given" in new Context { @@ -145,21 +145,21 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) val loginInfo = LoginInfo("credentials", "1") service.save(loginInfo, passwordInfo) must beEqualTo(passwordInfo).awaitWithPatience - there was one(passwordInfoDAO).save(loginInfo, passwordInfo) + verify(passwordInfoDAO).save(loginInfo, passwordInfo) } "delegate the OAuth1Info to the correct DAO" in new Context { val loginInfo = LoginInfo("credentials", "1") service.save(loginInfo, oauth1Info) must beEqualTo(oauth1Info).awaitWithPatience - there was one(oauth1InfoDAO).save(loginInfo, oauth1Info) + verify(oauth1InfoDAO).save(loginInfo, oauth1Info) } "delegate the OAuth2Info to the correct DAO" in new Context { val loginInfo = LoginInfo("credentials", "1") service.save(loginInfo, oauth2Info) must beEqualTo(oauth2Info).awaitWithPatience - there was one(oauth2InfoDAO).save(loginInfo, oauth2Info) + verify(oauth2InfoDAO).save(loginInfo, oauth2Info) } "throw a ConfigurationException if an unsupported type was given" in new Context { @@ -178,7 +178,7 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) Await.result(passwordInfoDAO.add(loginInfo, passwordInfo), 10 seconds) service.remove[PasswordInfo](loginInfo) must beEqualTo(()).awaitWithPatience - there was one(passwordInfoDAO).remove(loginInfo) + verify(passwordInfoDAO).remove(loginInfo) } "delegate the OAuth1Info to the correct DAO" in new Context { @@ -187,7 +187,7 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) Await.result(oauth1InfoDAO.add(loginInfo, oauth1Info), 10 seconds) service.remove[OAuth1Info](loginInfo) must beEqualTo(()).awaitWithPatience - there was one(oauth1InfoDAO).remove(loginInfo) + verify(oauth1InfoDAO).remove(loginInfo) } "delegate the OAuth2Info to the correct DAO" in new Context { @@ -196,7 +196,7 @@ class DelegableAuthInfoRepositorySpec(implicit ev: ExecutionEnv) Await.result(oauth2InfoDAO.add(loginInfo, oauth2Info), 10 seconds) service.remove[OAuth2Info](loginInfo) must beEqualTo(()).awaitWithPatience - there was one(oauth2InfoDAO).remove(loginInfo) + verify(oauth2InfoDAO).remove(loginInfo) } "throw a ConfigurationException if an unsupported type was given" in new Context { diff --git a/silhouette-totp/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/GoogleTotpProviderSpec.scala b/silhouette-totp/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/GoogleTotpProviderSpec.scala index b58c25e4..65f626d9 100644 --- a/silhouette-totp/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/GoogleTotpProviderSpec.scala +++ b/silhouette-totp/src/test/scala/io/github/honeycombcheesecake/play/silhouette/impl/providers/GoogleTotpProviderSpec.scala @@ -17,7 +17,8 @@ package io.github.honeycombcheesecake.play.silhouette.impl.providers import io.github.honeycombcheesecake.play.silhouette.api.util.{ Credentials, PasswordInfo } import com.warrenstrange.googleauth.GoogleAuthenticator -import org.specs2.mock.Mockito +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any import play.api.test.WithApplication import scala.concurrent.ExecutionContext.Implicits.global @@ -25,7 +26,7 @@ import scala.concurrent.ExecutionContext.Implicits.global /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.providers.GoogleTotpProvider#GoogleTOTPProvider]] class. */ -class GoogleTotpProviderSpec extends PasswordProviderSpec with Mockito { +class GoogleTotpProviderSpec extends PasswordProviderSpec { "The `authenticate` with verification code method" should { "return None when the sharedKey is null or empty" in new WithApplication with Context { await(provider.authenticate(null.asInstanceOf[String], testVerificationCode)) should be(None) @@ -51,9 +52,9 @@ class GoogleTotpProviderSpec extends PasswordProviderSpec with Mockito { "The `createCredentials` method" should { "return the correct TotpCredentials shared key" in new WithApplication with Context { val result = provider.createCredentials(credentials.identifier) - result.totpInfo.sharedKey must not be empty - result.totpInfo.scratchCodes must not be empty - result.qrUrl must not be empty + result.totpInfo.sharedKey.nonEmpty must beTrue + result.totpInfo.scratchCodes.nonEmpty must beTrue + result.qrUrl.nonEmpty must beTrue } } @@ -73,8 +74,8 @@ class GoogleTotpProviderSpec extends PasswordProviderSpec with Mockito { } "return Some(PasswordInfo,TotpInfo) when the plain scratch code is valid" in new WithApplication with Context { - fooHasher.hash(any()) returns testPasswordInfo - barHasher.matches(testPasswordInfo, testScratchCode) returns true + when(fooHasher.hash(any())).thenReturn(testPasswordInfo) + when(barHasher.matches(testPasswordInfo, testScratchCode)).thenReturn(true) val result = provider.createCredentials(credentials.identifier) await(provider.authenticate(result.totpInfo, testScratchCode)) should not be empty } diff --git a/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticator.scala b/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticator.scala index c888db2a..0cc93aa0 100644 --- a/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticator.scala +++ b/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticator.scala @@ -280,7 +280,7 @@ class CookieAuthenticatorService( val combinedCookies = filteredCookies :+ cookie val cookies = Cookies(combinedCookies) - request.withAttrs(request.attrs + RequestAttrKey.Cookies.bindValue(Cell(cookies))) + request.withAttrs(request.attrs.updated(RequestAttrKey.Cookies, Cell(cookies))) } /** diff --git a/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticator.scala b/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticator.scala index 3ffe6bad..62fddbbe 100644 --- a/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticator.scala +++ b/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticator.scala @@ -214,7 +214,7 @@ class SessionAuthenticatorService( case None => session } - request.withAttrs(request.attrs + RequestAttrKey.Session.bindValue(Cell(s))) + request.withAttrs(request.attrs.updated(RequestAttrKey.Session, Cell(s))) } /** diff --git a/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandler.scala b/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandler.scala index ef344c41..9c2efc2a 100644 --- a/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandler.scala +++ b/silhouette/app/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandler.scala @@ -209,4 +209,4 @@ case class CsrfStateSettings( secureCookie: Boolean = true, httpOnlyCookie: Boolean = true, sameSite: Option[Cookie.SameSite] = Some(Cookie.SameSite.Lax), - expirationTime: FiniteDuration = 5 minutes) + expirationTime: FiniteDuration = 5.minutes) diff --git a/silhouette/test/Helpers.scala b/silhouette/test/Helpers.scala index 59186fd9..45f36c18 100644 --- a/silhouette/test/Helpers.scala +++ b/silhouette/test/Helpers.scala @@ -19,7 +19,6 @@ import io.github.honeycombcheesecake.play.silhouette.api.AuthInfo import io.github.honeycombcheesecake.play.silhouette.impl.providers.{ SocialProfile, SocialStateItem, StatefulAuthInfo } import org.specs2.execute.{ AsResult, Result => Specs2Result } import org.specs2.matcher.{ JsonMatchers, MatchResult } -import org.specs2.mock.Mockito import org.specs2.mutable.Around import play.api.libs.json.{ JsValue, Json } import play.api.mvc.{ Result => PlayResult } @@ -28,6 +27,7 @@ import play.api.test.PlaySpecification import scala.concurrent.Future import scala.io.{ Codec, Source } import scala.reflect.ClassTag +import org.mockito.Mockito /** * Executes a before method in the context of the around method. @@ -63,7 +63,7 @@ trait BeforeAfterWithinAround extends Around { /** * Base test case for the social providers. */ -trait SocialProviderSpec[A <: AuthInfo] extends PlaySpecification with Mockito with JsonMatchers { +trait SocialProviderSpec[A <: AuthInfo] extends PlaySpecification with JsonMatchers { /** * Applies a matcher on a simple result. @@ -121,7 +121,7 @@ trait SocialProviderSpec[A <: AuthInfo] extends PlaySpecification with Mockito w lazy val result = await(providerResult.failed) - result must not(throwAn[E]) + result must not[Throwable](throwAn[E]) result.rethrow must throwAn[E].like(f) } } @@ -177,4 +177,15 @@ object Helper { case None => throw new Exception("Cannot load file: " + file) } } + + /** + * Mock related helpers + */ + + def mock[A](implicit a: ClassTag[A]): A = + Mockito.mock(a.runtimeClass).asInstanceOf[A] + + def mockSmart[A](implicit a: ClassTag[A]): A = + Mockito.mock(a.runtimeClass, Mockito.withSettings().defaultAnswer(Mockito.RETURNS_SMART_NULLS)).asInstanceOf[A] + } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/SecuredActionSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/SecuredActionSpec.scala index 9c47bfae..d56c70e6 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/SecuredActionSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/SecuredActionSpec.scala @@ -26,7 +26,6 @@ import io.github.honeycombcheesecake.play.silhouette.api.services.{ Authenticato import net.codingwell.scalaguice.ScalaModule import org.specs2.control.NoLanguageFeatures import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.inject.bind import play.api.inject.guice.GuiceApplicationBuilder @@ -34,6 +33,9 @@ import play.api.libs.json.Json import play.api.mvc.Results._ import play.api.mvc._ import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ +import test.Helper.mock import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -44,13 +46,13 @@ import scala.reflect.ClassTag /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.api.actions.SecuredActionSpec]]. */ -class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers with NoLanguageFeatures { +class SecuredActionSpec extends PlaySpecification with JsonMatchers with NoLanguageFeatures { "The `SecuredAction` action" should { "restrict access if no valid authenticator can be retrieved" in new InjectorContext { new WithApplication(app) with Context { withEvent[NotAuthenticatedEvent] { - env.authenticatorService.retrieve(any()) returns Future.successful(None) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) val result = controller.defaultAction(request) @@ -63,9 +65,9 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "restrict access and discard authenticator if an invalid authenticator can be retrieved" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator.copy(isValid = false))) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator.copy(isValid = false)))) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } withEvent[NotAuthenticatedEvent] { @@ -73,7 +75,7 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers status(result) must equalTo(UNAUTHORIZED) contentAsString(result) must contain("global.not.authenticated") - there was one(env.authenticatorService).discard(any(), any())(any()) + verify(env.authenticatorService).discard(any(), any())(any()) theProbe.expectMsg(500 millis, NotAuthenticatedEvent(request)) } } @@ -81,18 +83,18 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "restrict access and discard authenticator if no identity could be found for an authenticator" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(None) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(None)) withEvent[NotAuthenticatedEvent] { val result = controller.defaultAction(request) status(result) must equalTo(UNAUTHORIZED) contentAsString(result) must contain("global.not.authenticated") - there was one(env.authenticatorService).discard(any(), any())(any()) + verify(env.authenticatorService).discard(any(), any())(any()) theProbe.expectMsg(500 millis, NotAuthenticatedEvent(request)) } } @@ -100,11 +102,11 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "display local not-authenticated result if user isn't authenticated[authorization and error handler]" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(None) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(None)) val result = controller.actionWithAuthorizationAndErrorHandler(request) @@ -115,11 +117,11 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "display local not-authenticated result if user isn't authenticated[error handler only]" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(None) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(None)) val result = controller.actionWithErrorHandler(request) @@ -130,11 +132,11 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "display global not-authenticated result if user isn't authenticated" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(None) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(None)) val result = controller.defaultAction(request) @@ -145,20 +147,20 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "restrict access and update authenticator if a user is authenticated but not authorized" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) - authorization.isAuthorized(any(), any())(any()) returns Future.successful(false) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) + when(authorization.isAuthorized(any(), any())(any())).thenReturn(Future.successful(false)) withEvent[NotAuthorizedEvent[FakeIdentity]] { val result = controller.actionWithAuthorization(request) status(result) must equalTo(FORBIDDEN) contentAsString(result) must contain("global.not.authorized") - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).update(any(), any())(any()) theProbe.expectMsg(500 millis, NotAuthorizedEvent(identity, request)) } } @@ -166,58 +168,58 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "display local not-authorized result if user isn't authorized" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) - authorization.isAuthorized(any(), any())(any()) returns Future.successful(false) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) + when(authorization.isAuthorized(any(), any())(any())).thenReturn(Future.successful(false)) val result = controller.actionWithAuthorizationAndErrorHandler(request) status(result) must equalTo(FORBIDDEN) contentAsString(result) must contain("local.not.authorized") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) } } "display global not-authorized result if user isn't authorized" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) - authorization.isAuthorized(any(), any())(any()) returns Future.successful(false) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) + when(authorization.isAuthorized(any(), any())(any())).thenReturn(Future.successful(false)) val result = controller.actionWithAuthorization(request) status(result) must equalTo(FORBIDDEN) contentAsString(result) must contain("global.not.authorized") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) } } "invoke action without authorization if user is authenticated" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -225,20 +227,20 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "invoke action with authorization if user is authenticated but not authorized" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.actionWithAuthorization(request) status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -246,25 +248,25 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "use next request provider in the chain if first isn't responsible" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(None) - basicAuthRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.init(any())(any[RequestHeader]()) answers { p: Any => - Future.successful(p.asInstanceOf[FakeAuthenticator#Value]) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(None)) + when(basicAuthRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.init(any())(any[RequestHeader]())).thenAnswer { p => + Future.successful(p.getArgument(0).asInstanceOf[FakeAuthenticator#Value]) } - env.authenticatorService.embed(any(), any[Result]())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.embed(any(), any[Result]())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.actionWithAuthorization(request) status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).init(any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).init(any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -272,11 +274,11 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "update an initialized authenticator if it was touched" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } withEvent[AuthenticatedEvent[FakeIdentity]] { @@ -284,8 +286,8 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -293,17 +295,17 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "do not update an initialized authenticator if it was not touched" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Right(authenticator) - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Right(authenticator)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.actionWithAuthorization(request) status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).touch(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -311,24 +313,24 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "init an uninitialized authenticator" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.init(any())(any[RequestHeader]()) answers { p: Any => - Future.successful(p.asInstanceOf[FakeAuthenticator#Value]) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.init(any())(any[RequestHeader]())).thenAnswer { p => + Future.successful(p.getArgument(0).asInstanceOf[FakeAuthenticator#Value]) } - env.authenticatorService.embed(any(), any[Result]())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.embed(any(), any[Result]())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.actionWithAuthorization(request) status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).init(any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).init(any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -336,21 +338,21 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "renew an initialized authenticator" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.renew(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.renew(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.renewAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("renewed") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).renew(any(), any())(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).renew(any(), any())(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -358,21 +360,21 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "renew an uninitialized authenticator" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.renew(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.renew(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.renewAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("renewed") - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).renew(any(), any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).renew(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -380,21 +382,21 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "discard an initialized authenticator" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.discardAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("discarded") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).discard(any(), any())(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).discard(any(), any())(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -402,20 +404,20 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "discard an uninitialized authenticator" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.discardAction(request) status(result) must equalTo(OK) - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).discard(any(), any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).discard(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, request)) } } @@ -425,12 +427,12 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers new WithApplication(app) with Context { implicit val req = FakeRequest().withHeaders("Accept" -> "application/json") - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) withEvent[AuthenticatedEvent[FakeIdentity]] { val result = controller.defaultAction(req) @@ -438,8 +440,8 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers status(result) must equalTo(OK) contentType(result) must beSome("application/json") contentAsString(result) must /("result" -> "full.access") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) theProbe.expectMsg(500 millis, AuthenticatedEvent(identity, req)) } } @@ -449,31 +451,31 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "The `SecuredRequestHandler`" should { "return status 401 if authentication was not successful" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(None) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) val result = controller.defaultHandler(request) status(result) must equalTo(UNAUTHORIZED) - there was no(env.authenticatorService).touch(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService, never()).touch(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) } } "return the user if authentication was successful" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultHandler(request) status(result) must equalTo(OK) contentAsString(result) must */("providerID" -> "test") and */("providerKey" -> "1") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) } } } @@ -481,9 +483,9 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "The `exceptionHandler` method of the SecuredErrorHandler" should { "translate an ForbiddenException into a 403 Forbidden result" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } val failed = Future.failed(new NotAuthorizedException("Access denied")) @@ -495,9 +497,9 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers "translate an UnauthorizedException into a 401 Unauthorized result" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } val failed = Future.failed(new NotAuthenticatedException("Not authenticated")) @@ -527,7 +529,7 @@ class SecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers */ lazy val authorization = { val a = mock[Authorization[SecuredEnv#I, SecuredEnv#A]] - a.isAuthorized(any(), any())(any()) returns Future.successful(true) + when(a.isAuthorized(any(), any())(any())).thenReturn(Future.successful(true)) a } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UnsecuredActionSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UnsecuredActionSpec.scala index d0891e5e..cda9a062 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UnsecuredActionSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UnsecuredActionSpec.scala @@ -26,13 +26,15 @@ import io.github.honeycombcheesecake.play.silhouette.api.services.{ Authenticato import net.codingwell.scalaguice.ScalaModule import org.specs2.control.NoLanguageFeatures import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.inject.bind import play.api.inject.guice.GuiceApplicationBuilder import play.api.mvc.Results._ import play.api.mvc._ import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ +import test.Helper.mock import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -41,12 +43,12 @@ import scala.reflect.ClassTag /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.api.actions.UnsecuredActionSpec]]. */ -class UnsecuredActionSpec extends PlaySpecification with Mockito with JsonMatchers with NoLanguageFeatures { +class UnsecuredActionSpec extends PlaySpecification with JsonMatchers with NoLanguageFeatures { "The `UnsecuredAction` action" should { "grant access if no valid authenticator can be retrieved" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(None) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(None)) val result = controller.defaultAction(request) @@ -57,43 +59,43 @@ class UnsecuredActionSpec extends PlaySpecification with Mockito with JsonMatche "grant access and discard authenticator if an invalid authenticator can be retrieved" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(Some(authenticator.copy(isValid = false))) - env.authenticatorService.discard(any, any)(any) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(Some(authenticator.copy(isValid = false)))) + when(env.authenticatorService.discard(any, any)(any)).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).discard(any, any)(any) + verify(env.authenticatorService).discard(any, any)(any) } } "grant access and discard authenticator if no identity could be found for an authenticator" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(Some(authenticator)) - env.authenticatorService.discard(any, any)(any) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.discard(any, any)(any)).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(None) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(None)) val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("full.access") - there was one(env.authenticatorService).discard(any, any)(any) + verify(env.authenticatorService).discard(any, any)(any) } } "display local not-authorized result if user is authenticated" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any) returns Left(authenticator) - env.authenticatorService.update(any, any)(any) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any)).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any, any)(any)).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.actionWithErrorHandler(request) @@ -104,12 +106,12 @@ class UnsecuredActionSpec extends PlaySpecification with Mockito with JsonMatche "display global not-authorized result if user is authenticated" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any) returns Left(authenticator) - env.authenticatorService.update(any, any)(any) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any)).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any, any)(any)).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultAction(request) @@ -122,31 +124,31 @@ class UnsecuredActionSpec extends PlaySpecification with Mockito with JsonMatche "The `UnsecuredRequestHandler`" should { "return status 403 if user is authenticated" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any) returns Left(authenticator) - env.authenticatorService.update(any, any)(any) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any)).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any, any)(any)).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultHandler(request) status(result) must equalTo(FORBIDDEN) - there was one(env.authenticatorService).touch(any) - there was one(env.authenticatorService).update(any, any)(any) + verify(env.authenticatorService).touch(any) + verify(env.authenticatorService).update(any, any)(any) } } "return the data if user is not authenticated" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(None) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(None)) val result = controller.defaultHandler(request) status(result) must equalTo(OK) contentAsString(result) must be equalTo "data" - there was no(env.authenticatorService).touch(any) - there was no(env.authenticatorService).update(any, any)(any) + verify(env.authenticatorService, never()).touch(any) + verify(env.authenticatorService, never()).update(any, any)(any) } } } @@ -154,9 +156,9 @@ class UnsecuredActionSpec extends PlaySpecification with Mockito with JsonMatche "The `exceptionHandler` method of the UnsecuredErrorHandler" should { "translate an ForbiddenException into a 403 Forbidden result" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any) returns Future.successful(None) - env.authenticatorService.discard(any, any)(any) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any)).thenReturn(Future.successful(None)) + when(env.authenticatorService.discard(any, any)(any)).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } val failed = Future.failed(new NotAuthorizedException("Access denied")) diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UserAwareActionSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UserAwareActionSpec.scala index c484b8cb..ca0daaf3 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UserAwareActionSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/api/actions/UserAwareActionSpec.scala @@ -23,13 +23,15 @@ import io.github.honeycombcheesecake.play.silhouette.api.services.{ Authenticato import net.codingwell.scalaguice.ScalaModule import org.specs2.control.NoLanguageFeatures import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.i18n.{ Lang, Langs, MessagesApi } import play.api.inject.guice.GuiceApplicationBuilder import play.api.libs.json.Json import play.api.mvc.{ ControllerComponents, _ } import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ +import test.Helper.mock import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -37,12 +39,12 @@ import scala.concurrent.Future /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.api.actions.UserAwareAction]]. */ -class UserAwareActionSpec extends PlaySpecification with Mockito with JsonMatchers with NoLanguageFeatures { +class UserAwareActionSpec extends PlaySpecification with JsonMatchers with NoLanguageFeatures { "The `UserAwareAction` action" should { "invoke action without identity and authenticator if no authenticator could be found" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(None) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) val result = controller.defaultAction(request) @@ -53,201 +55,201 @@ class UserAwareActionSpec extends PlaySpecification with Mockito with JsonMatche "invoke action without identity and authenticator if invalid authenticator was found" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator.copy(isValid = false))) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator.copy(isValid = false)))) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain(messagesApi("without.identity.and.authenticator")) - there was one(env.authenticatorService).discard(any(), any())(any()) + verify(env.authenticatorService).discard(any(), any())(any()) } } "invoke action with valid authenticator if no identity could be found" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(None) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(None)) val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain(messagesApi("without.identity.and.with.authenticator")) - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) } } "invoke action with authenticator and identity" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain(messagesApi("with.identity.and.authenticator")) - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) } } "use next request provider in the chain if first isn't responsible" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(None) - basicAuthRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.init(any())(any()) answers { p: Any => Future.successful(p.asInstanceOf[FakeAuthenticator#Value]) } - env.authenticatorService.embed(any(), any[Result]())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(None)) + when(basicAuthRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.init(any())(any())).thenAnswer { p: Any => Future.successful(p.asInstanceOf[FakeAuthenticator#Value]) } + when(env.authenticatorService.embed(any(), any[Result]())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("with.identity.and.authenticator") - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).init(any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).init(any())(any()) } } "update an initialized authenticator if it was touched" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("with.identity.and.authenticator") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) } } "do not update an initialized authenticator if it was not touched" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Right(authenticator) - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Right(authenticator)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain(messagesApi("with.identity.and.authenticator")) - there was one(env.authenticatorService).touch(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) } } "init an uninitialized authenticator" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.init(any())(any()) answers { p: Any => Future.successful(p.asInstanceOf[FakeAuthenticator#Value]) } - env.authenticatorService.embed(any(), any[Result]())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.init(any())(any())).thenAnswer { p: Any => Future.successful(p.asInstanceOf[FakeAuthenticator#Value]) } + when(env.authenticatorService.embed(any(), any[Result]())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("with.identity.and.authenticator") - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).init(any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).init(any())(any()) } } "renew an initialized authenticator" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.renew(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.renew(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.renewAction(request) status(result) must equalTo(OK) contentAsString(result) must contain(messagesApi("renewed")) - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).renew(any(), any())(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).renew(any(), any())(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) } } "renew an uninitialized authenticator" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.renew(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.renew(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.renewAction(request) status(result) must equalTo(OK) contentAsString(result) must contain("renewed") - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).renew(any(), any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).renew(any(), any())(any()) } } "discard an initialized authenticator" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.discardAction(request) status(result) must equalTo(OK) contentAsString(result) must contain(messagesApi("discarded")) - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).discard(any(), any())(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).discard(any(), any())(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) } } "discard an uninitialized authenticator" in new InjectorContext with WithRequestProvider { new WithApplication(app) with Context { - tokenRequestProvider.authenticate(any()) returns Future.successful(Some(identity.loginInfo)) - env.authenticatorService.retrieve(any()) returns Future.successful(None) - env.authenticatorService.create(any())(any()) returns Future.successful(authenticator) - env.authenticatorService.discard(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(tokenRequestProvider.authenticate(any())).thenReturn(Future.successful(Some(identity.loginInfo))) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) + when(env.authenticatorService.create(any())(any())).thenReturn(Future.successful(authenticator)) + when(env.authenticatorService.discard(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.discardAction(request) status(result) must equalTo(OK) - there was one(env.authenticatorService).create(any())(any()) - there was one(env.authenticatorService).discard(any(), any())(any()) + verify(env.authenticatorService).create(any())(any()) + verify(env.authenticatorService).discard(any(), any())(any()) } } } @@ -255,31 +257,31 @@ class UserAwareActionSpec extends PlaySpecification with Mockito with JsonMatche "The `UserAwareRequestHandler`" should { "return status 401 if authentication was not successful" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(None) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(None)) val result = controller.defaultHandler(request) status(result) must equalTo(UNAUTHORIZED) - there was no(env.authenticatorService).touch(any()) - there was no(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService, never()).touch(any()) + verify(env.authenticatorService, never()).update(any(), any())(any()) } } "return the user if authentication was successful" in new InjectorContext { new WithApplication(app) with Context { - env.authenticatorService.retrieve(any()) returns Future.successful(Some(authenticator)) - env.authenticatorService.touch(any()) returns Left(authenticator) - env.authenticatorService.update(any(), any())(any()) answers { (a, m) => - Future.successful(AuthenticatorResult(a.asInstanceOf[Array[Any]](1).asInstanceOf[Result])) + when(env.authenticatorService.retrieve(any())).thenReturn(Future.successful(Some(authenticator))) + when(env.authenticatorService.touch(any())).thenReturn(Left(authenticator)) + when(env.authenticatorService.update(any(), any())(any())).thenAnswer { m => + Future.successful(AuthenticatorResult(m.getArgument(1).asInstanceOf[Result])) } - env.identityService.retrieve(identity.loginInfo) returns Future.successful(Some(identity)) + when(env.identityService.retrieve(identity.loginInfo)).thenReturn(Future.successful(Some(identity))) val result = controller.defaultHandler(request) status(result) must equalTo(OK) contentAsString(result) must */("providerID" -> "test") and */("providerKey" -> "1") - there was one(env.authenticatorService).touch(any()) - there was one(env.authenticatorService).update(any(), any())(any()) + verify(env.authenticatorService).touch(any()) + verify(env.authenticatorService).update(any(), any())(any()) } } } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/BearerTokenAuthenticatorSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/BearerTokenAuthenticatorSpec.scala index 3ff6e12d..a831aba5 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/BearerTokenAuthenticatorSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/BearerTokenAuthenticatorSpec.scala @@ -23,10 +23,12 @@ import io.github.honeycombcheesecake.play.silhouette.api.services.AuthenticatorS import io.github.honeycombcheesecake.play.silhouette.api.util.{ RequestPart, Clock, IDGenerator } import io.github.honeycombcheesecake.play.silhouette.impl.authenticators.BearerTokenAuthenticatorService._ import org.specs2.control.NoLanguageFeatures -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.mvc.Results import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mockSmart import java.time.ZonedDateTime import scala.concurrent.ExecutionContext.Implicits.global @@ -37,7 +39,7 @@ import scala.language.postfixOps /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.authenticators.BearerTokenAuthenticator]]. */ -class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with NoLanguageFeatures { +class BearerTokenAuthenticatorSpec extends PlaySpecification with NoLanguageFeatures { "The `isValid` method of the authenticator" should { "return false if the authenticator is expired" in new Context { @@ -61,8 +63,8 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N implicit val request = FakeRequest() val id = "test-id" - idGenerator.generate returns Future.successful(id) - clock.now returns ZonedDateTime.now + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(ZonedDateTime.now) await(service.create(loginInfo)).id must be equalTo id } @@ -71,8 +73,8 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N implicit val request = FakeRequest() val now = ZonedDateTime.now - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service.create(loginInfo)).lastUsedDateTime must be equalTo now } @@ -81,8 +83,8 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N implicit val request = FakeRequest() val now = ZonedDateTime.now - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service.create(loginInfo)).expirationDateTime must be equalTo now + 12.hours } @@ -92,9 +94,9 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N val sixHours = 6 hours val now = ZonedDateTime.now - settings.authenticatorExpiry returns sixHours - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(settings.authenticatorExpiry).thenReturn(sixHours) + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service.create(loginInfo)).expirationDateTime must be equalTo now + sixHours } @@ -102,7 +104,7 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "throws an AuthenticatorCreationException exception if an error occurred during creation" in new Context { implicit val request = FakeRequest() - idGenerator.generate returns Future.failed(new Exception("Could not generate ID")) + when(idGenerator.generate).thenReturn(Future.failed(new Exception("Could not generate ID"))) await(service.create(loginInfo)) must throwA[AuthenticatorCreationException].like { case e => @@ -121,7 +123,7 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "return None if no authenticator is stored for the token located in the headers" in new Context { implicit val request = FakeRequest().withHeaders(settings.fieldName -> authenticator.id) - repository.find(authenticator.id) returns Future.successful(None) + when(repository.find(authenticator.id)).thenReturn(Future.successful(None)) await(service.retrieve) must beNone } @@ -129,7 +131,7 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "return authenticator if an authenticator is stored for token located in the header" in new Context { implicit val request = FakeRequest().withHeaders(settings.fieldName -> authenticator.id) - repository.find(authenticator.id) returns Future.successful(Some(authenticator)) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator))) await(service.retrieve) must beSome(authenticator) } @@ -137,8 +139,8 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "return authenticator if an authenticator is stored for the token located in the query string" in new Context { implicit val request = FakeRequest("GET", s"?${settings.fieldName}=${authenticator.id}") - settings.requestParts returns Some(Seq(RequestPart.QueryString)) - repository.find(authenticator.id) returns Future.successful(Some(authenticator)) + when(settings.requestParts).thenReturn(Some(Seq(RequestPart.QueryString))) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator))) await(service.retrieve) must beSome(authenticator) } @@ -146,7 +148,7 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "throws an AuthenticatorRetrievalException exception if an error occurred during retrieval" in new Context { implicit val request = FakeRequest().withHeaders(settings.fieldName -> authenticator.id) - repository.find(authenticator.id) returns Future.failed(new RuntimeException("Cannot find authenticator")) + when(repository.find(authenticator.id)).thenReturn(Future.failed(new RuntimeException("Cannot find authenticator"))) await(service.retrieve) must throwA[AuthenticatorRetrievalException].like { case e => @@ -157,17 +159,17 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "The `init` method of the service" should { "save the authenticator in backing store" in new Context { - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[BearerTokenAuthenticator]) } + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[BearerTokenAuthenticator]) } implicit val request = FakeRequest() val token = await(service.init(authenticator)) token must be equalTo authenticator.id - there was one(repository).add(authenticator) + verify(repository).add(authenticator) } "throws an AuthenticatorInitializationException exception if an error occurred during initialization" in new Context { - repository.add(any()) returns Future.failed(new Exception("Cannot store authenticator")) + when(repository.add(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) implicit val request = FakeRequest() @@ -222,8 +224,8 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "The `touch` method of the service" should { "update the last used date if idle timeout is defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns Some(1 second) - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(Some(1 second)) + when(clock.now).thenReturn(ZonedDateTime.now) service.touch(authenticator) must beLeft[BearerTokenAuthenticator].like { case a => @@ -232,8 +234,8 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N } "do not update the last used date if idle timeout is not defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns None - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(None) + when(clock.now).thenReturn(ZonedDateTime.now) service.touch(authenticator) must beRight[BearerTokenAuthenticator].like { case a => @@ -244,17 +246,17 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "The `update` method of the service" should { "update the authenticator in backing store" in new Context { - repository.update(any()) answers { _: Any => Future.successful(authenticator) } + when(repository.update(any())).thenAnswer { _ => Future.successful(authenticator) } implicit val request = FakeRequest() await(service.update(authenticator, Results.Ok)) - there was one(repository).update(authenticator) + verify(repository).update(authenticator) } "return the result if the authenticator could be stored in backing store" in new Context { - repository.update(any()) answers { p: Any => Future.successful(p.asInstanceOf[BearerTokenAuthenticator]) } + when(repository.update(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[BearerTokenAuthenticator]) } implicit val request = FakeRequest() val result = service.update(authenticator, Results.Ok) @@ -263,7 +265,7 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N } "throws an AuthenticatorUpdateException exception if an error occurred during update" in new Context { - repository.update(any()) returns Future.failed(new Exception("Cannot store authenticator")) + when(repository.update(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) implicit val request = FakeRequest() @@ -280,14 +282,14 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N val now = ZonedDateTime.now val id = "new-test-id" - repository.remove(authenticator.id) returns Future.successful(()) - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[BearerTokenAuthenticator]) } - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(repository.remove(authenticator.id)).thenReturn(Future.successful(())) + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[BearerTokenAuthenticator]) } + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) await(service.renew(authenticator, Results.Ok)) - there was one(repository).remove(authenticator.id) + verify(repository).remove(authenticator.id) } "renew the authenticator and return the response with a new bearer token" in new Context { @@ -295,10 +297,10 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N val now = ZonedDateTime.now val id = "new-test-id" - repository.remove(any()) returns Future.successful(()) - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[BearerTokenAuthenticator]) } - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(repository.remove(any())).thenReturn(Future.successful(())) + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[BearerTokenAuthenticator]) } + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) val result = service.renew(authenticator, Results.Ok) @@ -310,10 +312,10 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N val now = ZonedDateTime.now val id = "new-test-id" - repository.remove(any()) returns Future.successful(()) - repository.add(any()) returns Future.failed(new Exception("Cannot store authenticator")) - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(repository.remove(any())).thenReturn(Future.successful(())) + when(repository.add(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) await(service.renew(authenticator, Results.Ok)) must throwA[AuthenticatorRenewalException].like { case e => @@ -326,18 +328,18 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N "remove authenticator from backing store" in new Context { implicit val request = FakeRequest() - repository.remove(authenticator.id) returns Future.successful(authenticator) + when(repository.remove(authenticator.id)).thenReturn(Future.successful(authenticator)) await(service.discard(authenticator, Results.Ok)) - there was one(repository).remove(authenticator.id) + verify(repository).remove(authenticator.id) } "throws an AuthenticatorDiscardingException exception if an error occurred during discarding" in new Context { implicit val request = FakeRequest() val okResult = Results.Ok - repository.remove(authenticator.id) returns Future.failed(new Exception("Cannot remove authenticator")) + when(repository.remove(authenticator.id)).thenReturn(Future.failed(new Exception("Cannot remove authenticator"))) await(service.discard(authenticator, okResult)) must throwA[AuthenticatorDiscardingException].like { case e => @@ -354,17 +356,17 @@ class BearerTokenAuthenticatorSpec extends PlaySpecification with Mockito with N /** * The repository implementation. */ - lazy val repository = mock[AuthenticatorRepository[BearerTokenAuthenticator]].smart + lazy val repository = mockSmart[AuthenticatorRepository[BearerTokenAuthenticator]] /** * The ID generator implementation. */ - lazy val idGenerator = mock[IDGenerator].smart + lazy val idGenerator = mockSmart[IDGenerator] /** * The clock implementation. */ - lazy val clock = mock[Clock].smart + lazy val clock = mockSmart[Clock] /** * The settings. diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticatorSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticatorSpec.scala index 8b9030e2..3056bb8a 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticatorSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/CookieAuthenticatorSpec.scala @@ -28,10 +28,12 @@ import io.github.honeycombcheesecake.play.silhouette.impl.authenticators.CookieA import io.github.honeycombcheesecake.play.silhouette.impl.authenticators.CookieAuthenticatorService._ import org.specs2.control.NoLanguageFeatures import org.specs2.matcher.MatchResult -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.mvc.{ Cookie, DefaultCookieHeaderEncoding, Results } import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mockSmart import java.time.ZonedDateTime import scala.concurrent.ExecutionContext.Implicits.global @@ -43,7 +45,7 @@ import scala.util.{ Failure, Success } /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.authenticators.CookieAuthenticator]]. */ -class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLanguageFeatures { +class CookieAuthenticatorSpec extends PlaySpecification with NoLanguageFeatures { "The `isValid` method of the authenticator" should { "return false if the authenticator is expired" in new Context { @@ -66,13 +68,13 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "sign the cookie" in new WithApplication with Context { serialize(authenticator, signer, authenticatorEncoder) - there was one(signer).sign(any()) + verify(signer).sign(any()) } "encode the cookie" in new WithApplication with Context { serialize(authenticator, signer, authenticatorEncoder) - there was one(authenticatorEncoder).encode(any()) + verify(authenticatorEncoder).encode(any()) } } @@ -95,7 +97,7 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang val value = "value" val msg = "^" + Pattern.quote(InvalidCookieSignature.format(ID, "")) + ".*" - signer.extract(any()) returns Failure(new Exception("invalid")) + when(signer.extract(any())).thenReturn(Failure(new Exception("invalid"))) unserialize(authenticatorEncoder.encode(value), signer, authenticatorEncoder) must beFailedTry.withThrowable[AuthenticatorException](msg) } @@ -113,10 +115,10 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "return a fingerprinted authenticator" in new Context { implicit val request = FakeRequest() - idGenerator.generate returns Future.successful("test-id") - clock.now returns ZonedDateTime.now - fingerprintGenerator.generate(any()) returns "test" - settings.useFingerprinting returns true + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(ZonedDateTime.now) + when(fingerprintGenerator.generate(any())).thenReturn("test") + when(settings.useFingerprinting).thenReturn(true) await(service(Some(repository)).create(loginInfo)).fingerprint must beSome("test") } @@ -124,9 +126,9 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "return a non fingerprinted authenticator" in new Context { implicit val request = FakeRequest() - idGenerator.generate returns Future.successful("test-id") - clock.now returns ZonedDateTime.now - settings.useFingerprinting returns false + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(ZonedDateTime.now) + when(settings.useFingerprinting).thenReturn(false) await(service(Some(repository)).create(loginInfo)).fingerprint must beNone } @@ -135,8 +137,8 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang implicit val request = FakeRequest() val id = "test-id" - idGenerator.generate returns Future.successful(id) - clock.now returns ZonedDateTime.now + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(ZonedDateTime.now) await(service(Some(repository)).create(loginInfo)).id must be equalTo id } @@ -145,8 +147,8 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang implicit val request = FakeRequest() val now = ZonedDateTime.now - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service(Some(repository)).create(loginInfo)).lastUsedDateTime must be equalTo now } @@ -155,8 +157,8 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang implicit val request = FakeRequest() val now = ZonedDateTime.now - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service(Some(repository)).create(loginInfo)).expirationDateTime must be equalTo now + 12.hours } @@ -166,9 +168,9 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang val sixHours = 6 hours val now = ZonedDateTime.now - settings.authenticatorExpiry returns sixHours - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(settings.authenticatorExpiry).thenReturn(sixHours) + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service(Some(repository)).create(loginInfo)).expirationDateTime must be equalTo now + sixHours } @@ -176,7 +178,7 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "throws an AuthenticatorCreationException exception if an error occurred during creation" in new Context { implicit val request = FakeRequest() - idGenerator.generate returns Future.failed(new Exception("Could not generate ID")) + when(idGenerator.generate).thenReturn(Future.failed(new Exception("Could not generate ID"))) await(service(Some(repository)).create(loginInfo)) must throwA[AuthenticatorCreationException].like { case e => @@ -195,7 +197,7 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "[stateful] return None if no authenticator for the cookie is stored in backing store" in new Context { implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, authenticator.id)) - repository.find(authenticator.id) returns Future.successful(None) + when(repository.find(authenticator.id)).thenReturn(Future.successful(None)) await(service(Some(repository)).retrieve) must beNone } @@ -204,68 +206,68 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, authenticatorEncoder.encode("invalid"))) await(service(None).retrieve) must beNone - there was no(repository).find(any()) + verify(repository, never()).find(any()) } "[stateful] return None if authenticator fingerprint doesn't match current fingerprint" in new Context { implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, authenticator.id)) - fingerprintGenerator.generate(any()) returns "false" - settings.useFingerprinting returns true - authenticator.fingerprint returns Some("test") - repository.find(authenticator.id) returns Future.successful(Some(authenticator)) + when(fingerprintGenerator.generate(any())).thenReturn("false") + when(settings.useFingerprinting).thenReturn(true) + when(authenticator.fingerprint).thenReturn(Some("test")) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator))) await(service(Some(repository)).retrieve) must beNone } "[stateless] return None if authenticator fingerprint doesn't match current fingerprint" in new WithApplication with Context { - fingerprintGenerator.generate(any()) returns "false" - settings.useFingerprinting returns true - authenticator.fingerprint returns Some("test") + when(fingerprintGenerator.generate(any())).thenReturn("false") + when(settings.useFingerprinting).thenReturn(true) + when(authenticator.fingerprint).thenReturn(Some("test")) implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, serialize(authenticator, signer, authenticatorEncoder))) await(service(None).retrieve) must beNone - there was no(repository).find(any()) + verify(repository, never()).find(any()) } "[stateful] return authenticator if authenticator fingerprint matches current fingerprint" in new Context { implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, authenticator.id)) - fingerprintGenerator.generate(any()) returns "test" - settings.useFingerprinting returns true - authenticator.fingerprint returns Some("test") - repository.find(authenticator.id) returns Future.successful(Some(authenticator)) + when(fingerprintGenerator.generate(any())).thenReturn("test") + when(settings.useFingerprinting).thenReturn(true) + when(authenticator.fingerprint).thenReturn(Some("test")) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator))) await(service(Some(repository)).retrieve) must beSome(authenticator) } "[stateless] return authenticator if authenticator fingerprint matches current fingerprint" in new WithApplication with Context { - fingerprintGenerator.generate(any()) returns "test" - settings.useFingerprinting returns true - authenticator.fingerprint returns Some("test") + when(fingerprintGenerator.generate(any())).thenReturn("test") + when(settings.useFingerprinting).thenReturn(true) + when(authenticator.fingerprint).thenReturn(Some("test")) implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, serialize(authenticator, signer, authenticatorEncoder))) await(service(None).retrieve) must beSome(authenticator) - there was no(repository).find(any()) + verify(repository, never()).find(any()) } "[stateful] return authenticator if fingerprinting is disabled" in new Context { implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, authenticator.id)) - settings.useFingerprinting returns false - repository.find(authenticator.id) returns Future.successful(Some(authenticator)) + when(settings.useFingerprinting).thenReturn(false) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator))) await(service(Some(repository)).retrieve) must beSome(authenticator) } "[stateless] return authenticator if fingerprinting is disabled" in new WithApplication with Context { - settings.useFingerprinting returns false + when(settings.useFingerprinting).thenReturn(false) implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, serialize(authenticator, signer, authenticatorEncoder))) - repository.find(authenticator.id) returns Future.successful(Some(authenticator)) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator))) await(service(None).retrieve) must beSome(authenticator) } @@ -273,9 +275,9 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "throws an AuthenticatorRetrievalException exception if an error occurred during retrieval" in new Context { implicit val request = FakeRequest().withCookies(Cookie(settings.cookieName, authenticator.id)) - fingerprintGenerator.generate(any()) throws new RuntimeException("Could not generate fingerprint") - settings.useFingerprinting returns true - repository.find(authenticator.id) returns Future.successful(Some(authenticator)) + when(fingerprintGenerator.generate(any())).thenThrow(new RuntimeException("Could not generate fingerprint")) + when(settings.useFingerprinting).thenReturn(true) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator))) await(service(Some(repository)).retrieve) must throwA[AuthenticatorRetrievalException].like { case e => @@ -286,12 +288,12 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "The `init` method of the service" should { "[stateful] return a cookie with the authenticator ID if the authenticator could be saved in backing store" in new Context { - repository.add(any()) answers { _: Any => Future.successful(authenticator) } + when(repository.add(any())).thenAnswer { _ => Future.successful(authenticator) } implicit val request = FakeRequest() await(service(Some(repository)).init(authenticator)) must be equalTo statefulCookie - there was one(repository).add(any()) + verify(repository).add(any()) } "[stateless] return a cookie with a serialized authenticator" in new WithApplication with Context { @@ -300,11 +302,11 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang val cookie = await(service(None).init(authenticator)) unserialize(cookie.value, signer, authenticatorEncoder) must be equalTo unserialize(statelessCookie.value, signer, authenticatorEncoder) - there was no(repository).add(any()) + verify(repository, never()).add(any()) } "throws an AuthenticatorInitializationException exception if an error occurred during initialization" in new Context { - repository.add(any()) returns Future.failed(new Exception("Cannot store authenticator")) + when(repository.add(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) implicit val request = FakeRequest() @@ -358,8 +360,8 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "The `touch` method of the service" should { "update the last used date if idle timeout is defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns Some(1 second) - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(Some(1 second)) + when(clock.now).thenReturn(ZonedDateTime.now) service(Some(repository)).touch(authenticator) must beLeft[CookieAuthenticator].like { case a => @@ -368,8 +370,8 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang } "do not update the last used date if idle timeout is not defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns None - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(None) + when(clock.now).thenReturn(ZonedDateTime.now) service(Some(repository)).touch(authenticator) must beRight[CookieAuthenticator].like { case a => @@ -380,17 +382,17 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "The `update` method of the service" should { "[stateful] update the authenticator in backing store" in new Context { - repository.update(any()) answers { _: Any => Future.successful(authenticator) } + when(repository.update(any())).thenAnswer { _ => Future.successful(authenticator) } implicit val request = FakeRequest() await(service(Some(repository)).update(authenticator, Results.Ok)) - there was one(repository).update(authenticator) + verify(repository).update(authenticator) } "[stateful] return the result if the authenticator could be stored in backing store" in new Context { - repository.update(any()) answers { p: Any => Future.successful(p.asInstanceOf[CookieAuthenticator]) } + when(repository.update(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[CookieAuthenticator]) } implicit val request = FakeRequest() val result = service(Some(repository)).update(authenticator, Results.Ok) @@ -404,11 +406,11 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang status(result) must be equalTo OK cookies(result).get(settings.cookieName) should beSome[Cookie].which(statelessResponseCookieMatcher(authenticator)) - there was no(repository).update(authenticator) + verify(repository, never()).update(authenticator) } "throws an AuthenticatorUpdateException exception if an error occurred during update" in new Context { - repository.update(any()) returns Future.failed(new Exception("Cannot store authenticator")) + when(repository.update(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) implicit val request = FakeRequest() @@ -425,14 +427,14 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang val now = ZonedDateTime.now val id = "new-test-id" - repository.remove(authenticator.id) returns Future.successful(()) - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[CookieAuthenticator]) } - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(repository.remove(authenticator.id)).thenReturn(Future.successful(())) + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[CookieAuthenticator]) } + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) await(service(Some(repository)).renew(authenticator, Results.Ok)) - there was one(repository).remove(authenticator.id) + verify(repository).remove(authenticator.id) } "[stateful] renew the authenticator and return the response with the updated cookie value" in new Context { @@ -440,15 +442,15 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang val now = ZonedDateTime.now val id = "new-test-id" - repository.remove(any()) returns Future.successful(()) - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[CookieAuthenticator]) } - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(repository.remove(any())).thenReturn(Future.successful(())) + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[CookieAuthenticator]) } + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) val result = service(Some(repository)).renew(authenticator, Results.Ok) cookies(result).get(settings.cookieName) should beSome[Cookie].which(statefulResponseCookieMatcher(id)) - there was one(repository).add(any()) + verify(repository).add(any()) } "[stateless] renew the authenticator and return the response with the updated cookie value" in new WithApplication with Context { @@ -456,15 +458,15 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang val now = ZonedDateTime.now val id = "new-test-id" - settings.useFingerprinting returns false - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(settings.useFingerprinting).thenReturn(false) + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) val result = service(None).renew(authenticator, Results.Ok) cookies(result).get(settings.cookieName) should beSome[Cookie].which(statelessResponseCookieMatcher( authenticator.copy(id = id, lastUsedDateTime = now, expirationDateTime = now + settings.authenticatorExpiry))) - there was no(repository).add(any()) + verify(repository, never()).add(any()) } "throws an AuthenticatorRenewalException exception if an error occurred during renewal" in new Context { @@ -472,10 +474,10 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang val now = ZonedDateTime.now val id = "new-test-id" - repository.remove(any()) returns Future.successful(()) - repository.add(any()) returns Future.failed(new Exception("Cannot store authenticator")) - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(repository.remove(any())).thenReturn(Future.successful(())) + when(repository.add(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) await(service(Some(repository)).renew(authenticator, Results.Ok)) must throwA[AuthenticatorRenewalException].like { case e => @@ -488,7 +490,7 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang "[stateful] discard the cookie from response and remove it from backing store" in new Context { implicit val request = FakeRequest() - repository.remove(any()) returns Future.successful(()) + when(repository.remove(any())).thenReturn(Future.successful(())) val result = service(Some(repository)).discard(authenticator, Results.Ok.withCookies(statefulCookie)) @@ -500,7 +502,7 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang c.domain must be equalTo settings.cookieDomain c.secure must be equalTo settings.secureCookie } - there was one(repository).remove(authenticator.id) + verify(repository).remove(authenticator.id) } "[stateless] discard the cookie from response" in new WithApplication with Context { @@ -515,14 +517,14 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang c.domain must be equalTo settings.cookieDomain c.secure must be equalTo settings.secureCookie } - there was no(repository).remove(authenticator.id) + verify(repository, never()).remove(authenticator.id) } "throws an AuthenticatorDiscardingException exception if an error occurred during discarding" in new Context { implicit val request = FakeRequest() val okResult = Results.Ok - repository.remove(any()) returns Future.failed(new Exception("Cannot store authenticator")) + when(repository.remove(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) await(service(Some(repository)).discard(authenticator, okResult)) must throwA[AuthenticatorDiscardingException].like { case e => @@ -539,27 +541,27 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang /** * The repository implementation. */ - lazy val repository = mock[AuthenticatorRepository[CookieAuthenticator]].smart + lazy val repository = mockSmart[AuthenticatorRepository[CookieAuthenticator]] /** * The ID generator implementation. */ - lazy val fingerprintGenerator = mock[FingerprintGenerator].smart + lazy val fingerprintGenerator = mockSmart[FingerprintGenerator] /** * The ID generator implementation. */ - lazy val idGenerator = mock[IDGenerator].smart + lazy val idGenerator = mockSmart[IDGenerator] /** * The signer implementation. * - * The signer returns the same value as passed to the methods. This is enough for testing. + * The signer).thenReturn(the same value as passed to the methods. This is enough for testing.) */ lazy val signer = { - val c = mock[Signer].smart - c.sign(any()) answers { p: Any => p.asInstanceOf[String] } - c.extract(any()) answers { p: Any => Success(p.asInstanceOf[String]) } + val c = mockSmart[Signer] + when(c.sign(any())).thenAnswer { _.getArgument(0).asInstanceOf[String] } + when(c.extract(any())).thenAnswer { p => Success(p.getArgument(0).asInstanceOf[String]) } c } @@ -574,7 +576,7 @@ class CookieAuthenticatorSpec extends PlaySpecification with Mockito with NoLang /** * The clock implementation. */ - lazy val clock = mock[Clock].smart + lazy val clock = mockSmart[Clock] /** * The settings. diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/DummyAuthenticatorSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/DummyAuthenticatorSpec.scala index 44fb372d..ec193e7b 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/DummyAuthenticatorSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/DummyAuthenticatorSpec.scala @@ -17,7 +17,6 @@ package io.github.honeycombcheesecake.play.silhouette.impl.authenticators import io.github.honeycombcheesecake.play.silhouette.api.LoginInfo import io.github.honeycombcheesecake.play.silhouette.api.services.AuthenticatorResult -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.mvc.Results import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } @@ -27,7 +26,7 @@ import scala.concurrent.ExecutionContext.Implicits.global /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.authenticators.DummyAuthenticator]]. */ -class DummyAuthenticatorSpec extends PlaySpecification with Mockito { +class DummyAuthenticatorSpec extends PlaySpecification { "The `isValid` method of the authenticator" should { "return true" in new Context { diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/JWTAuthenticatorSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/JWTAuthenticatorSpec.scala index d3c1e645..db314592 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/JWTAuthenticatorSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/JWTAuthenticatorSpec.scala @@ -27,11 +27,13 @@ import io.github.honeycombcheesecake.play.silhouette.impl.authenticators.JWTAuth import io.github.honeycombcheesecake.play.silhouette.impl.authenticators.JWTAuthenticatorService._ import org.specs2.control.NoLanguageFeatures import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.libs.json.{ JsNull, JsObject, Json } import play.api.mvc.Results import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mockSmart import java.time.temporal.ChronoField import java.time.{ ZoneId, ZonedDateTime } @@ -43,7 +45,7 @@ import scala.language.postfixOps /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.authenticators.JWTAuthenticator]]. */ -class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatchers with NoLanguageFeatures { +class JWTAuthenticatorSpec extends PlaySpecification with JsonMatchers with NoLanguageFeatures { "The `isValid` method of the authenticator" should { "return false if the authenticator is expired" in new Context { @@ -163,7 +165,7 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch val jwt: String = serialize(authenticatorCustomClock, authenticatorEncoder, settings) - clock.now returns lastUsedDateTime + when(clock.now).thenReturn(lastUsedDateTime) implicit val customClock: Option[Clock] = Some(clock) unserialize(jwt, authenticatorEncoder, settings) must beSuccessfulTry.withValue(authenticatorCustomClock.copy( @@ -194,8 +196,8 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch implicit val request = FakeRequest() val id = "test-id" - idGenerator.generate returns Future.successful(id) - clock.now returns ZonedDateTime.now + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(ZonedDateTime.now) await(service(None).create(loginInfo)).id must be equalTo id } @@ -204,8 +206,8 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch implicit val request = FakeRequest() val now = ZonedDateTime.now - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service(None).create(loginInfo)).lastUsedDateTime must be equalTo now } @@ -214,8 +216,8 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch implicit val request = FakeRequest() val now = ZonedDateTime.now - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service(None).create(loginInfo)).expirationDateTime must be equalTo now + 12.hours } @@ -225,9 +227,9 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch val sixHours = 6 hours val now = ZonedDateTime.now - settings.authenticatorExpiry returns sixHours - idGenerator.generate returns Future.successful("test-id") - clock.now returns now + when(settings.authenticatorExpiry).thenReturn(sixHours) + when(idGenerator.generate).thenReturn(Future.successful("test-id")) + when(clock.now).thenReturn(now) await(service(None).create(loginInfo)).expirationDateTime must be equalTo now + sixHours } @@ -235,7 +237,7 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "throws an AuthenticatorCreationException exception if an error occurred during creation" in new Context { implicit val request = FakeRequest() - idGenerator.generate returns Future.failed(new Exception("Could not generate ID")) + when(idGenerator.generate).thenReturn(Future.failed(new Exception("Could not generate ID"))) await(service(None).create(loginInfo)) must throwA[AuthenticatorCreationException].like { case e => @@ -254,18 +256,18 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "return None if DAO is enabled and no authenticator is stored for the token located in the header" in new Context { implicit val request = FakeRequest().withHeaders(settings.fieldName -> "not-stored") - repository.find(authenticator.id) returns Future.successful(None) + when(repository.find(authenticator.id)).thenReturn(Future.successful(None)) await(service(Some(repository)).retrieve) must beNone } "return authenticator if DAO is enabled and an authenticator is stored for the token located in the the header" in new WithApplication with Context { implicit val request = FakeRequest().withHeaders(settings.fieldName -> serialize(authenticator, authenticatorEncoder, settings)) - clock.now returns ZonedDateTime.now + when(clock.now).thenReturn(ZonedDateTime.now) - repository.find(authenticator.id) returns Future.successful(Some(authenticator.copy( + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator.copy( expirationDateTime = authenticator.expirationDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0), - lastUsedDateTime = authenticator.lastUsedDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0)))) + lastUsedDateTime = authenticator.lastUsedDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0))))) await(service(Some(repository)).retrieve) must beSome(authenticator.copy( expirationDateTime = authenticator.expirationDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0), @@ -274,12 +276,12 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "return authenticator if DAO is enabled and an authenticator is stored for the token located in the the query string" in new WithApplication with Context { implicit val request = FakeRequest("GET", s"?${settings.fieldName}=${serialize(authenticator, authenticatorEncoder, settings)}") - clock.now returns ZonedDateTime.now + when(clock.now).thenReturn(ZonedDateTime.now) - settings.requestParts returns Some(Seq(RequestPart.QueryString)) - repository.find(authenticator.id) returns Future.successful(Some(authenticator.copy( + when(settings.requestParts).thenReturn(Some(Seq(RequestPart.QueryString))) + when(repository.find(authenticator.id)).thenReturn(Future.successful(Some(authenticator.copy( expirationDateTime = authenticator.expirationDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0), - lastUsedDateTime = authenticator.lastUsedDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0)))) + lastUsedDateTime = authenticator.lastUsedDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0))))) await(service(Some(repository)).retrieve) must beSome(authenticator.copy( expirationDateTime = authenticator.expirationDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0), @@ -288,30 +290,30 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "return authenticator if DAO is disabled and authenticator was found in the header" in new WithApplication with Context { implicit val request = FakeRequest().withHeaders(settings.fieldName -> serialize(authenticator, authenticatorEncoder, settings)) - clock.now returns ZonedDateTime.now + when(clock.now).thenReturn(ZonedDateTime.now) await(service(None).retrieve) must beSome(authenticator.copy( expirationDateTime = authenticator.expirationDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0), lastUsedDateTime = authenticator.lastUsedDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0))) - there was no(repository).find(any()) + verify(repository, never()).find(any()) } "return authenticator if DAO is disabled and authenticator was found in the query string" in new WithApplication with Context { implicit val request = FakeRequest("GET", s"?${settings.fieldName}=${serialize(authenticator, authenticatorEncoder, settings)}") - clock.now returns ZonedDateTime.now + when(clock.now).thenReturn(ZonedDateTime.now) - settings.requestParts returns Some(Seq(RequestPart.QueryString)) + when(settings.requestParts).thenReturn(Some(Seq(RequestPart.QueryString))) await(service(None).retrieve) must beSome(authenticator.copy( expirationDateTime = authenticator.expirationDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0), lastUsedDateTime = authenticator.lastUsedDateTime.`with`(ChronoField.MILLI_OF_SECOND, 0))) - there was no(repository).find(any()) + verify(repository, never()).find(any()) } "throws an AuthenticatorRetrievalException exception if an error occurred during retrieval" in new WithApplication with Context { implicit val request = FakeRequest().withHeaders(settings.fieldName -> serialize(authenticator, authenticatorEncoder, settings)) - clock.now returns ZonedDateTime.now + when(clock.now).thenReturn(ZonedDateTime.now) - repository.find(authenticator.id) returns Future.failed(new RuntimeException("Cannot find authenticator")) + when(repository.find(authenticator.id)).thenReturn(Future.failed(new RuntimeException("Cannot find authenticator"))) await(service(Some(repository)).retrieve) must throwA[AuthenticatorRetrievalException].like { case e => @@ -322,13 +324,13 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "The `init` method of the service" should { "return the token if DAO is enabled and authenticator could be saved in backing store" in new WithApplication with Context { - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[JWTAuthenticator]) } + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[JWTAuthenticator]) } implicit val request = FakeRequest() val token = await(service(Some(repository)).init(authenticator)) unserialize(token, authenticatorEncoder, settings).get must be equalTo authenticator - there was one(repository).add(any()) + verify(repository).add(any()) } "return the token if DAO is disabled" in new WithApplication with Context { @@ -337,11 +339,11 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch val token = await(service(None).init(authenticator)) unserialize(token, authenticatorEncoder, settings).get must be equalTo authenticator - there was no(repository).add(any()) + verify(repository, never()).add(any()) } "throws an AuthenticatorInitializationException exception if an error occurred during initialization" in new Context { - repository.add(any()) returns Future.failed(new Exception("Cannot store authenticator")) + when(repository.add(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) implicit val request = FakeRequest() val okResult = Future.successful(Results.Ok) @@ -398,8 +400,8 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "The `touch` method of the service" should { "update the last used date if idle timeout is defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns Some(1 second) - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(Some(1 second)) + when(clock.now).thenReturn(ZonedDateTime.now) service(None).touch(authenticator) must beLeft[JWTAuthenticator].like { case a => @@ -408,8 +410,8 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch } "do not update the last used date if idle timeout is not defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns None - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(None) + when(clock.now).thenReturn(ZonedDateTime.now) service(None).touch(authenticator) must beRight[JWTAuthenticator].like { case a => @@ -420,39 +422,39 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "The `update` method of the service" should { "update the authenticator in backing store" in new WithApplication with Context { - repository.update(any()) answers { _: Any => Future.successful(authenticator) } + when(repository.update(any())).thenAnswer { _ => Future.successful(authenticator) } implicit val request = FakeRequest() await(service(Some(repository)).update(authenticator, Results.Ok)) - there was one(repository).update(authenticator) + verify(repository).update(authenticator) } "return the result if the authenticator could be stored in backing store" in new WithApplication with Context { - repository.update(any()) answers { p: Any => Future.successful(p.asInstanceOf[JWTAuthenticator]) } + when(repository.update(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[JWTAuthenticator]) } implicit val request = FakeRequest() val result = service(Some(repository)).update(authenticator, Results.Ok) status(result) must be equalTo OK unserialize(header(settings.fieldName, result).get, authenticatorEncoder, settings).get must be equalTo authenticator - there was one(repository).update(authenticator) + verify(repository).update(authenticator) } "return the result if backing store is disabled" in new WithApplication with Context { - repository.update(any()) answers { p: Any => Future.successful(p.asInstanceOf[JWTAuthenticator]) } + when(repository.update(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[JWTAuthenticator]) } implicit val request = FakeRequest() val result = service(None).update(authenticator, Results.Ok) status(result) must be equalTo OK unserialize(header(settings.fieldName, result).get, authenticatorEncoder, settings).get must be equalTo authenticator - there was no(repository).update(any()) + verify(repository, never()).update(any()) } "throws an AuthenticatorUpdateException exception if an error occurred during update" in new WithApplication with Context { - repository.update(any()) returns Future.failed(new Exception("Cannot store authenticator")) + when(repository.update(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) implicit val request = FakeRequest() @@ -468,10 +470,10 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch implicit val request = FakeRequest() val id = "new-test-id" - repository.remove(any()) answers { _: Any => Future.successful(()) } - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[JWTAuthenticator]) } - idGenerator.generate returns Future.successful(id) - clock.now returns ZonedDateTime.now.`with`(ChronoField.MILLI_OF_SECOND, 0) + when(repository.remove(any())).thenAnswer { _ => Future.successful(()) } + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[JWTAuthenticator]) } + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(ZonedDateTime.now.`with`(ChronoField.MILLI_OF_SECOND, 0)) val result = service(Some(repository)).renew(authenticator, Results.Ok) @@ -480,18 +482,18 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch expirationDateTime = clock.now + settings.authenticatorExpiry, lastUsedDateTime = clock.now) - there was one(repository).add(any()) - there was one(repository).remove(authenticator.id) + verify(repository).add(any()) + verify(repository).remove(authenticator.id) } "renew an authenticator with custom claims" in new WithApplication with Context { implicit val request = FakeRequest() val id = "new-test-id" - repository.remove(any()) returns Future.successful(()) - repository.add(any()) answers { p: Any => Future.successful(p.asInstanceOf[JWTAuthenticator]) } - idGenerator.generate returns Future.successful(id) - clock.now returns ZonedDateTime.now.`with`(ChronoField.MILLI_OF_SECOND, 0) + when(repository.remove(any())).thenReturn(Future.successful(())) + when(repository.add(any())).thenAnswer { p => Future.successful(p.getArgument(0).asInstanceOf[JWTAuthenticator]) } + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(ZonedDateTime.now.`with`(ChronoField.MILLI_OF_SECOND, 0)) val result = service(Some(repository)).renew(authenticator.copy(customClaims = Some(customClaims)), Results.Ok) @@ -501,16 +503,16 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch lastUsedDateTime = clock.now, customClaims = Some(customClaims)) - there was one(repository).add(any()) - there was one(repository).remove(authenticator.id) + verify(repository).add(any()) + verify(repository).remove(authenticator.id) } "renew the authenticator and return the response with a new JWT if DAO is disabled" in new WithApplication with Context { implicit val request = FakeRequest() val id = "new-test-id" - idGenerator.generate returns Future.successful(id) - clock.now returns ZonedDateTime.now.`with`(ChronoField.MILLI_OF_SECOND, 0) + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(ZonedDateTime.now.`with`(ChronoField.MILLI_OF_SECOND, 0)) val result = service(None).renew(authenticator, Results.Ok) @@ -518,8 +520,8 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch id = id, expirationDateTime = clock.now + settings.authenticatorExpiry, lastUsedDateTime = clock.now) - there was no(repository).remove(any()) - there was no(repository).add(any()) + verify(repository, never()).remove(any()) + verify(repository, never()).add(any()) } "throws an AuthenticatorRenewalException exception if an error occurred during renewal" in new Context { @@ -527,10 +529,10 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch val now = ZonedDateTime.now val id = "new-test-id" - repository.remove(any()) returns Future.successful(()) - repository.add(any()) returns Future.failed(new Exception("Cannot store authenticator")) - idGenerator.generate returns Future.successful(id) - clock.now returns now + when(repository.remove(any())).thenReturn(Future.successful(())) + when(repository.add(any())).thenReturn(Future.failed(new Exception("Cannot store authenticator"))) + when(idGenerator.generate).thenReturn(Future.successful(id)) + when(clock.now).thenReturn(now) await(service(Some(repository)).renew(authenticator, Results.Ok)) must throwA[AuthenticatorRenewalException].like { case e => @@ -543,11 +545,11 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch "remove authenticator from backing store if DAO is enabled" in new Context { implicit val request = FakeRequest() - repository.remove(authenticator.id) returns Future.successful(authenticator) + when(repository.remove(authenticator.id)).thenReturn(Future.successful(authenticator)) await(service(Some(repository)).discard(authenticator, Results.Ok)) - there was one(repository).remove(authenticator.id) + verify(repository).remove(authenticator.id) } "do not remove the authenticator from backing store if DAO is disabled" in new Context { @@ -555,14 +557,14 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch await(service(None).discard(authenticator, Results.Ok)) - there was no(repository).remove(authenticator.id) + verify(repository, never()).remove(authenticator.id) } "throws an AuthenticatorDiscardingException exception if an error occurred during discarding" in new Context { implicit val request = FakeRequest() val okResult = Results.Ok - repository.remove(authenticator.id) returns Future.failed(new Exception("Cannot remove authenticator")) + when(repository.remove(authenticator.id)).thenReturn(Future.failed(new Exception("Cannot remove authenticator"))) await(service(Some(repository)).discard(authenticator, okResult)) must throwA[AuthenticatorDiscardingException].like { case e => @@ -581,7 +583,7 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch /** * The repository implementation. */ - lazy val repository = mock[AuthenticatorRepository[JWTAuthenticator]].smart + lazy val repository = mockSmart[AuthenticatorRepository[JWTAuthenticator]] /** * The authenticator encoder implementation. @@ -591,12 +593,12 @@ class JWTAuthenticatorSpec extends PlaySpecification with Mockito with JsonMatch /** * The ID generator implementation. */ - lazy val idGenerator = mock[IDGenerator].smart + lazy val idGenerator = mockSmart[IDGenerator] /** * The clock implementation. */ - lazy val clock: Clock = mock[Clock].smart + lazy val clock: Clock = mockSmart[Clock] /** * The settings. diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticatorSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticatorSpec.scala index 01891f67..fae0804d 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticatorSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/authenticators/SessionAuthenticatorSpec.scala @@ -26,11 +26,13 @@ import io.github.honeycombcheesecake.play.silhouette.api.{ Authenticator, LoginI import io.github.honeycombcheesecake.play.silhouette.impl.authenticators.SessionAuthenticator._ import io.github.honeycombcheesecake.play.silhouette.impl.authenticators.SessionAuthenticatorService._ import org.specs2.control.NoLanguageFeatures -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.libs.json.Json import play.api.mvc._ import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.{ mockSmart, mock } import java.time.ZonedDateTime import scala.concurrent.ExecutionContext.Implicits.global @@ -41,7 +43,7 @@ import scala.language.postfixOps /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.authenticators.SessionAuthenticator]]. */ -class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLanguageFeatures { +class SessionAuthenticatorSpec extends PlaySpecification with NoLanguageFeatures { "The `isValid` method of the authenticator" should { "return false if the authenticator is expired" in new Context { @@ -88,9 +90,9 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "return a fingerprinted authenticator" in new Context { implicit val request = FakeRequest() - clock.now returns ZonedDateTime.now - fingerprintGenerator.generate(any) returns "test" - settings.useFingerprinting returns true + when(clock.now).thenReturn(ZonedDateTime.now) + when(fingerprintGenerator.generate(any)).thenReturn("test") + when(settings.useFingerprinting).thenReturn(true) await(service.create(loginInfo)).fingerprint must beSome("test") } @@ -98,8 +100,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "return a non fingerprinted authenticator" in new Context { implicit val request = FakeRequest() - clock.now returns ZonedDateTime.now - settings.useFingerprinting returns false + when(clock.now).thenReturn(ZonedDateTime.now) + when(settings.useFingerprinting).thenReturn(false) await(service.create(loginInfo)).fingerprint must beNone } @@ -108,7 +110,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan implicit val request = FakeRequest() val now = ZonedDateTime.now - clock.now returns now + when(clock.now).thenReturn(now) await(service.create(loginInfo)).lastUsedDateTime must be equalTo now } @@ -117,7 +119,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan implicit val request = FakeRequest() val now = ZonedDateTime.now - clock.now returns now + when(clock.now).thenReturn(now) await(service.create(loginInfo)).expirationDateTime must be equalTo now + 12.hours } @@ -127,8 +129,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan val sixHours = 6 hours val now = ZonedDateTime.now - clock.now returns now - settings.authenticatorExpiry returns sixHours + when(clock.now).thenReturn(now) + when(settings.authenticatorExpiry).thenReturn(sixHours) await(service.create(loginInfo)).expirationDateTime must be equalTo now + sixHours } @@ -136,7 +138,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "throws an AuthenticatorCreationException exception if an error occurred during creation" in new Context { implicit val request = FakeRequest() - clock.now throws new RuntimeException("Could not get date") + when(clock.now).thenThrow(new RuntimeException("Could not get date")) await(service.create(loginInfo)) must throwA[AuthenticatorCreationException].like { case e => @@ -155,7 +157,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "return None if session contains invalid json" in new WithApplication with Context { implicit val request = FakeRequest().withSession(settings.sessionKey -> authenticatorEncoder.encode("{")) - settings.useFingerprinting returns false + when(settings.useFingerprinting).thenReturn(false) await(service.retrieve) must beNone } @@ -163,15 +165,15 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "return None if session contains valid json but invalid authenticator" in new WithApplication with Context { implicit val request = FakeRequest().withSession(settings.sessionKey -> authenticatorEncoder.encode("{ \"test\": \"test\" }")) - settings.useFingerprinting returns false + when(settings.useFingerprinting).thenReturn(false) await(service.retrieve) must beNone } "return None if authenticator fingerprint doesn't match current fingerprint" in new WithApplication with Context { - fingerprintGenerator.generate(any) returns "false" - settings.useFingerprinting returns true - authenticator.fingerprint returns Some("test") + when(fingerprintGenerator.generate(any)).thenReturn("false") + when(settings.useFingerprinting).thenReturn(true) + when(authenticator.fingerprint).thenReturn(Some("test")) implicit val request = FakeRequest().withSession(settings.sessionKey -> authenticatorEncoder.encode(Json.toJson(authenticator).toString())) @@ -179,9 +181,9 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan } "return authenticator if authenticator fingerprint matches current fingerprint" in new WithApplication with Context { - fingerprintGenerator.generate(any) returns "test" - settings.useFingerprinting returns true - authenticator.fingerprint returns Some("test") + when(fingerprintGenerator.generate(any)).thenReturn("test") + when(settings.useFingerprinting).thenReturn(true) + when(authenticator.fingerprint).thenReturn(Some("test")) implicit val request = FakeRequest().withSession(settings.sessionKey -> authenticatorEncoder.encode(Json.toJson(authenticator).toString())) @@ -191,7 +193,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "return authenticator if fingerprinting is disabled" in new WithApplication with Context { implicit val request = FakeRequest().withSession(settings.sessionKey -> authenticatorEncoder.encode(Json.toJson(authenticator).toString())) - settings.useFingerprinting returns false + when(settings.useFingerprinting).thenReturn(false) await(service.retrieve) must beSome(authenticator) } @@ -200,7 +202,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan implicit val request = FakeRequest() .withSession(settings.sessionKey -> authenticatorEncoder.encode(Json.toJson(authenticator).toString())) - settings.useFingerprinting returns false + when(settings.useFingerprinting).thenReturn(false) await(service.retrieve) must beSome(authenticator) } @@ -208,8 +210,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "throws an AuthenticatorRetrievalException exception if an error occurred during retrieval" in new WithApplication with Context { implicit val request = FakeRequest().withSession(settings.sessionKey -> authenticatorEncoder.encode(Json.toJson(authenticator).toString())) - fingerprintGenerator.generate(any) throws new RuntimeException("Could not generate fingerprint") - settings.useFingerprinting returns true + when(fingerprintGenerator.generate(any)).thenThrow(new RuntimeException("Could not generate fingerprint")) + when(settings.useFingerprinting).thenReturn(true) await(service.retrieve) must throwA[AuthenticatorRetrievalException].like { case e => @@ -312,8 +314,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "The `touch` method of the service" should { "update the last used date if idle timeout is defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns Some(1 second) - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(Some(1 second)) + when(clock.now).thenReturn(ZonedDateTime.now) service.touch(authenticator) must beLeft[SessionAuthenticator].like { case a => @@ -322,8 +324,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan } "do not update the last used date if idle timeout is not defined" in new WithApplication with Context { - settings.authenticatorIdleTimeout returns None - clock.now returns ZonedDateTime.now + when(settings.authenticatorIdleTimeout).thenReturn(None) + when(clock.now).thenReturn(ZonedDateTime.now) service.touch(authenticator) must beRight[SessionAuthenticator].like { case a => @@ -362,7 +364,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan "throws an AuthenticatorUpdateException exception if an error occurred during update" in new Context { implicit val request = spy(FakeRequest()) - request.session throws new RuntimeException("Cannot get session") + when(request.session).thenThrow(new RuntimeException("Cannot get session")) await(service.update(authenticator, Results.Ok)) must throwA[AuthenticatorUpdateException].like { case e => @@ -379,8 +381,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan lastUsedDateTime = now, expirationDateTime = now + settings.authenticatorExpiry)).toString()) - settings.useFingerprinting returns false - clock.now returns now + when(settings.useFingerprinting).thenReturn(false) + when(clock.now).thenReturn(now) val result = service.renew(authenticator, Results.Ok) @@ -391,8 +393,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan implicit val request = FakeRequest().withSession(settings.sessionKey -> "existing") val now = ZonedDateTime.now - settings.useFingerprinting returns false - clock.now returns now + when(settings.useFingerprinting).thenReturn(false) + when(clock.now).thenReturn(now) val result = service.renew(authenticator, Results.Ok) @@ -405,8 +407,8 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan implicit val request = FakeRequest().withSession("request-other" -> "keep") val now = ZonedDateTime.now - settings.useFingerprinting returns false - clock.now returns now + when(settings.useFingerprinting).thenReturn(false) + when(clock.now).thenReturn(now) val result = service.renew(authenticator, Results.Ok.addingToSession( "result-other" -> "keep")) @@ -423,9 +425,9 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan val now = ZonedDateTime.now val okResult = (_: Authenticator) => Future.successful(Results.Ok) - request.session throws new RuntimeException("Cannot get session") - settings.useFingerprinting returns false - clock.now returns now + when(request.session).thenThrow(new RuntimeException("Cannot get session")) + when(settings.useFingerprinting).thenReturn(false) + when(clock.now).thenReturn(now) await(service.renew(authenticator, Results.Ok)) must throwA[AuthenticatorRenewalException].like { case e => @@ -457,7 +459,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan implicit val request = spy(FakeRequest()).withSession(settings.sessionKey -> "test") val result = mock[Result] - result.removingFromSession(any)(any) throws new RuntimeException("Cannot get session") + when(result.removingFromSession(any)(any)).thenThrow(new RuntimeException("Cannot get session")) await(service.discard(authenticator, result)) must throwA[AuthenticatorDiscardingException].like { case e => @@ -474,7 +476,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan /** * The ID generator implementation. */ - lazy val fingerprintGenerator = mock[FingerprintGenerator].smart + lazy val fingerprintGenerator = mockSmart[FingerprintGenerator] /** * The authenticator encoder implementation. @@ -484,7 +486,7 @@ class SessionAuthenticatorSpec extends PlaySpecification with Mockito with NoLan /** * The clock implementation. */ - lazy val clock = mock[Clock].smart + lazy val clock = mockSmart[Clock] /** * The settings. diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/BasicAuthProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/BasicAuthProviderSpec.scala index 48f94168..7ada25fb 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/BasicAuthProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/BasicAuthProviderSpec.scala @@ -21,6 +21,7 @@ import io.github.honeycombcheesecake.play.silhouette.api.exceptions._ import io.github.honeycombcheesecake.play.silhouette.api.util._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.PasswordProvider._ import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -36,7 +37,7 @@ class BasicAuthProviderSpec extends PasswordProviderSpec { val loginInfo = LoginInfo(provider.id, credentials.identifier) val request = FakeRequest().withHeaders(AUTHORIZATION -> encodeCredentials(credentials)) - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) await(provider.authenticate(request)) must throwA[ConfigurationException].like { case e => e.getMessage must beEqualTo(HasherIsNotRegistered.format(provider.id, "unknown", "foo, bar")) @@ -47,7 +48,7 @@ class BasicAuthProviderSpec extends PasswordProviderSpec { val loginInfo = new LoginInfo(provider.id, credentials.identifier) val request = FakeRequest().withHeaders(AUTHORIZATION -> encodeCredentials(credentials)) - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(None) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(None)) await(provider.authenticate(request)) must beNone } @@ -57,8 +58,8 @@ class BasicAuthProviderSpec extends PasswordProviderSpec { val loginInfo = LoginInfo(provider.id, credentials.identifier) val request = FakeRequest().withHeaders(AUTHORIZATION -> encodeCredentials(credentials)) - fooHasher.matches(passwordInfo, credentials.password) returns false - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) + when(fooHasher.matches(passwordInfo, credentials.password)).thenReturn(false) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) await(provider.authenticate(request)) must beNone } @@ -78,8 +79,8 @@ class BasicAuthProviderSpec extends PasswordProviderSpec { val loginInfo = LoginInfo(provider.id, credentials.identifier) val request = FakeRequest().withHeaders(AUTHORIZATION -> encodeCredentials(credentials)) - fooHasher.matches(passwordInfo, credentials.password) returns true - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) + when(fooHasher.matches(passwordInfo, credentials.password)).thenReturn(true) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) await(provider.authenticate(request)) must beSome(loginInfo) } @@ -90,8 +91,8 @@ class BasicAuthProviderSpec extends PasswordProviderSpec { val loginInfo = LoginInfo(provider.id, credentialsWithColon.identifier) val request = FakeRequest().withHeaders(AUTHORIZATION -> encodeCredentials(credentialsWithColon)) - fooHasher.matches(passwordInfo, credentialsWithColon.password) returns true - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) + when(fooHasher.matches(passwordInfo, credentialsWithColon.password)).thenReturn(true) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) await(provider.authenticate(request)) must beSome(loginInfo) } @@ -101,13 +102,13 @@ class BasicAuthProviderSpec extends PasswordProviderSpec { val loginInfo = LoginInfo(provider.id, credentials.identifier) val request = FakeRequest().withHeaders(AUTHORIZATION -> encodeCredentials(credentials)) - fooHasher.hash(credentials.password) returns passwordInfo - barHasher.matches(passwordInfo, credentials.password) returns true - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) - authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo) returns Future.successful(passwordInfo) + when(fooHasher.hash(credentials.password)).thenReturn(passwordInfo) + when(barHasher.matches(passwordInfo, credentials.password)).thenReturn(true) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) + when(authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo)).thenReturn(Future.successful(passwordInfo)) await(provider.authenticate(request)) must beSome(loginInfo) - there was one(authInfoRepository).update(loginInfo, passwordInfo) + verify(authInfoRepository).update(loginInfo, passwordInfo) } "re-hash password with new hasher if password info is deprecated" in new WithApplication with Context { @@ -115,14 +116,14 @@ class BasicAuthProviderSpec extends PasswordProviderSpec { val loginInfo = LoginInfo(provider.id, credentials.identifier) val request = FakeRequest().withHeaders(AUTHORIZATION -> encodeCredentials(credentials)) - fooHasher.isDeprecated(passwordInfo) returns Some(true) - fooHasher.hash(credentials.password) returns passwordInfo - fooHasher.matches(passwordInfo, credentials.password) returns true - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) - authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo) returns Future.successful(passwordInfo) + when(fooHasher.isDeprecated(passwordInfo)).thenReturn(Some(true)) + when(fooHasher.hash(credentials.password)).thenReturn(passwordInfo) + when(fooHasher.matches(passwordInfo, credentials.password)).thenReturn(true) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) + when(authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo)).thenReturn(Future.successful(passwordInfo)) await(provider.authenticate(request)) must beSome(loginInfo) - there was one(authInfoRepository).update(loginInfo, passwordInfo) + verify(authInfoRepository).update(loginInfo, passwordInfo) } "return None if Authorization method is not Basic and Base64 decoded header has ':'" in new WithApplication with Context { diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/CredentialsProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/CredentialsProviderSpec.scala index 93ca5b6b..515f008b 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/CredentialsProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/CredentialsProviderSpec.scala @@ -21,6 +21,7 @@ import io.github.honeycombcheesecake.play.silhouette.api.util.{ Credentials, Pas import io.github.honeycombcheesecake.play.silhouette.impl.exceptions.{ IdentityNotFoundException, InvalidPasswordException } import io.github.honeycombcheesecake.play.silhouette.impl.providers.PasswordProvider._ import play.api.test.WithApplication +import org.mockito.Mockito._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -34,7 +35,7 @@ class CredentialsProviderSpec extends PasswordProviderSpec { "throw IdentityNotFoundException if no auth info could be found for the given credentials" in new WithApplication with Context { val loginInfo = new LoginInfo(provider.id, credentials.identifier) - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(None) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(None)) await(provider.authenticate(credentials)) must throwA[IdentityNotFoundException].like { case e => e.getMessage must beEqualTo(PasswordInfoNotFound.format(provider.id, loginInfo)) @@ -45,8 +46,8 @@ class CredentialsProviderSpec extends PasswordProviderSpec { val passwordInfo = PasswordInfo("foo", "hashed(s3cr3t)") val loginInfo = LoginInfo(provider.id, credentials.identifier) - fooHasher.matches(passwordInfo, credentials.password) returns false - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) + when(fooHasher.matches(passwordInfo, credentials.password)).thenReturn(false) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) await(provider.authenticate(credentials)) must throwA[InvalidPasswordException].like { case e => e.getMessage must beEqualTo(PasswordDoesNotMatch.format(provider.id)) @@ -57,7 +58,7 @@ class CredentialsProviderSpec extends PasswordProviderSpec { val passwordInfo = PasswordInfo("unknown", "hashed(s3cr3t)") val loginInfo = LoginInfo(provider.id, credentials.identifier) - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) await(provider.authenticate(credentials)) must throwA[ConfigurationException].like { case e => e.getMessage must beEqualTo(HasherIsNotRegistered.format(provider.id, "unknown", "foo, bar")) @@ -68,8 +69,8 @@ class CredentialsProviderSpec extends PasswordProviderSpec { val passwordInfo = PasswordInfo("foo", "hashed(s3cr3t)") val loginInfo = LoginInfo(provider.id, credentials.identifier) - fooHasher.matches(passwordInfo, credentials.password) returns true - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) + when(fooHasher.matches(passwordInfo, credentials.password)).thenReturn(true) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) await(provider.authenticate(credentials)) must be equalTo loginInfo } @@ -78,27 +79,27 @@ class CredentialsProviderSpec extends PasswordProviderSpec { val passwordInfo = PasswordInfo("bar", "hashed(s3cr3t)") val loginInfo = LoginInfo(provider.id, credentials.identifier) - fooHasher.hash(credentials.password) returns passwordInfo - barHasher.matches(passwordInfo, credentials.password) returns true - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) - authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo) returns Future.successful(passwordInfo) + when(fooHasher.hash(credentials.password)).thenReturn(passwordInfo) + when(barHasher.matches(passwordInfo, credentials.password)).thenReturn(true) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) + when(authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo)).thenReturn(Future.successful(passwordInfo)) await(provider.authenticate(credentials)) must be equalTo loginInfo - there was one(authInfoRepository).update(loginInfo, passwordInfo) + verify(authInfoRepository).update(loginInfo, passwordInfo) } "re-hash password with new hasher if hasher is deprecated" in new WithApplication with Context { val passwordInfo = PasswordInfo("foo", "hashed(s3cr3t)") val loginInfo = LoginInfo(provider.id, credentials.identifier) - fooHasher.isDeprecated(passwordInfo) returns Some(true) - fooHasher.hash(credentials.password) returns passwordInfo - fooHasher.matches(passwordInfo, credentials.password) returns true - authInfoRepository.find[PasswordInfo](loginInfo) returns Future.successful(Some(passwordInfo)) - authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo) returns Future.successful(passwordInfo) + when(fooHasher.isDeprecated(passwordInfo)).thenReturn(Some(true)) + when(fooHasher.hash(credentials.password)).thenReturn(passwordInfo) + when(fooHasher.matches(passwordInfo, credentials.password)).thenReturn(true) + when(authInfoRepository.find[PasswordInfo](loginInfo)).thenReturn(Future.successful(Some(passwordInfo))) + when(authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo)).thenReturn(Future.successful(passwordInfo)) await(provider.authenticate(credentials)) must be equalTo loginInfo - there was one(authInfoRepository).update(loginInfo, passwordInfo) + verify(authInfoRepository).update(loginInfo, passwordInfo) } } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/DefaultSocialStateHandlerSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/DefaultSocialStateHandlerSpec.scala index 80323deb..0b996c96 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/DefaultSocialStateHandlerSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/DefaultSocialStateHandlerSpec.scala @@ -21,11 +21,13 @@ import io.github.honeycombcheesecake.play.silhouette.api.util.ExtractableRequest import io.github.honeycombcheesecake.play.silhouette.impl.providers.DefaultSocialStateHandler._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialStateItem.ItemStructure import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.libs.json.Json import play.api.mvc.Results import play.api.test.{ FakeRequest, PlaySpecification } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mockSmart import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -34,11 +36,11 @@ import scala.util.{ Failure, Success } /** * Test case for the [[DefaultSocialStateHandler]] class. */ -class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with JsonMatchers { +class DefaultSocialStateHandlerSpec extends PlaySpecification with JsonMatchers { "The `withHandler` method" should { "return a new state handler with the given item handler added" in new Context { - val newHandler = mock[SocialStateItemHandler].smart + val newHandler = mockSmart[SocialStateItemHandler] stateHandler.handlers.size must be equalTo 2 stateHandler.withHandler(newHandler).handlers.size must be equalTo 3 @@ -47,8 +49,8 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with "The `state` method" should { "return the social state" in new Context { - Default.itemHandler.item returns Future.successful(Default.item) - Publishable.itemHandler.item returns Future.successful(Publishable.item) + when(Default.itemHandler.item).thenReturn(Future.successful(Default.item)) + when(Publishable.itemHandler.item).thenReturn(Future.successful(Publishable.item)) await(stateHandler.state) must be equalTo state } @@ -66,13 +68,13 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with } "return the serialized social state" in new Context { - Default.itemHandler.canHandle(Publishable.item) returns None - Default.itemHandler.canHandle(Default.item) returns Some(Default.item) - Default.itemHandler.serialize(Default.item) returns Default.structure + when(Default.itemHandler.canHandle(Publishable.item)).thenReturn(None) + when(Default.itemHandler.canHandle(Default.item)).thenReturn(Some(Default.item)) + when(Default.itemHandler.serialize(Default.item)).thenReturn(Default.structure) - Publishable.itemHandler.canHandle(Default.item) returns None - Publishable.itemHandler.canHandle(Publishable.item) returns Some(Publishable.item) - Publishable.itemHandler.serialize(Publishable.item) returns Publishable.structure + when(Publishable.itemHandler.canHandle(Default.item)).thenReturn(None) + when(Publishable.itemHandler.canHandle(Publishable.item)).thenReturn(Some(Publishable.item)) + when(Publishable.itemHandler.serialize(Publishable.item)).thenReturn(Publishable.structure) stateHandler.serialize(state) must be equalTo s"${Publishable.structure.asString}.${Default.structure.asString}" } @@ -85,7 +87,7 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with await(stateHandler.unserialize("")) - there was no(signer).extract(any[String]()) + verify(signer, never()).extract(any[String]()) } "throw an Exception for an empty string" in new Context { @@ -111,8 +113,8 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with implicit val request = new ExtractableRequest(FakeRequest()) val serialized = s"${Default.structure.asString}" - Default.itemHandler.canHandle(any[ItemStructure]())(any()) returns false - Publishable.itemHandler.canHandle(any[ItemStructure]())(any()) returns false + when(Default.itemHandler.canHandle(any[ItemStructure]())(any())).thenReturn(false) + when(Publishable.itemHandler.canHandle(any[ItemStructure]())(any())).thenReturn(false) await(stateHandler.unserialize(serialized)) must throwA[ProviderException].like { case e => @@ -124,13 +126,13 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with implicit val request = new ExtractableRequest(FakeRequest()) val serialized = s"${Default.structure.asString}.${Publishable.structure.asString}" - Default.itemHandler.canHandle(Publishable.structure) returns false - Default.itemHandler.canHandle(Default.structure) returns true - Default.itemHandler.unserialize(Default.structure) returns Future.successful(Default.item) + when(Default.itemHandler.canHandle(Publishable.structure)).thenReturn(false) + when(Default.itemHandler.canHandle(Default.structure)).thenReturn(true) + when(Default.itemHandler.unserialize(Default.structure)).thenReturn(Future.successful(Default.item)) - Publishable.itemHandler.canHandle(Default.structure) returns false - Publishable.itemHandler.canHandle(Publishable.structure) returns true - Publishable.itemHandler.unserialize(Publishable.structure) returns Future.successful(Publishable.item) + when(Publishable.itemHandler.canHandle(Default.structure)).thenReturn(false) + when(Publishable.itemHandler.canHandle(Publishable.structure)).thenReturn(true) + when(Publishable.itemHandler.unserialize(Publishable.structure)).thenReturn(Future.successful(Publishable.item)) await(stateHandler.unserialize(serialized)) must be equalTo SocialState(Set(Default.item, Publishable.item)) } @@ -142,9 +144,9 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with val result = Results.Ok val publishedResult = Results.Ok.withHeaders("X-PUBLISHED" -> "true") - Publishable.itemHandler.publish(Publishable.item, result) returns publishedResult - Publishable.itemHandler.canHandle(Default.item) returns None - Publishable.itemHandler.canHandle(Publishable.item) returns Some(Publishable.item) + when(Publishable.itemHandler.publish(Publishable.item, result)).thenReturn(publishedResult) + when(Publishable.itemHandler.canHandle(Default.item)).thenReturn(None) + when(Publishable.itemHandler.canHandle(Publishable.item)).thenReturn(Some(Publishable.item)) stateHandler.publish(result, state) must be equalTo publishedResult } @@ -153,8 +155,8 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with implicit val request = FakeRequest() val result = Results.Ok - Publishable.itemHandler.canHandle(Default.item) returns None - Publishable.itemHandler.canHandle(Publishable.item) returns None + when(Publishable.itemHandler.canHandle(Default.item)).thenReturn(None) + when(Publishable.itemHandler.canHandle(Publishable.item)).thenReturn(None) stateHandler.publish(result, state) must be equalTo result } @@ -173,7 +175,7 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with type Item = DefaultItem } object Default { - val itemHandler = mock[DefaultItemHandler].smart + val itemHandler = mockSmart[DefaultItemHandler] val item = DefaultItem() val structure = ItemStructure("default", Json.obj()) } @@ -186,7 +188,7 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with type Item = PublishableItem } object Publishable { - val itemHandler = mock[PublishableItemHandler].smart + val itemHandler = mockSmart[PublishableItemHandler] val item = PublishableItem() val structure = ItemStructure("publishable", Json.obj()) } @@ -197,10 +199,10 @@ class DefaultSocialStateHandlerSpec extends PlaySpecification with Mockito with * The signer returns the same value as passed to the methods. This is enough for testing. */ val signer = { - val c = mock[Signer].smart - c.sign(any()) answers { p: Any => p.asInstanceOf[String] } - c.extract(any()) answers { p: Any => - p.asInstanceOf[String] match { + val c = mockSmart[Signer] + when(c.sign(any())).thenAnswer(_.getArgument(0).asInstanceOf[String]) + when(c.extract(any())).thenAnswer { p => + p.getArgument(0).asInstanceOf[String] match { case "" => Failure(new RuntimeException("Wrong state format")) case s => Success(s) } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth1ProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth1ProviderSpec.scala index 771383c5..2f32907c 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth1ProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth1ProviderSpec.scala @@ -20,12 +20,16 @@ import io.github.honeycombcheesecake.play.silhouette.impl.exceptions.{ AccessDen import io.github.honeycombcheesecake.play.silhouette.impl.providers.OAuth1Provider._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.services.PlayOAuth1Service import org.specs2.matcher.ThrownExpectations -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.mvc.{ AnyContent, AnyContentAsEmpty, Result, Results } import play.api.test.{ FakeHeaders, FakeRequest, WithApplication } import play.mvc.Http.HeaderNames +import org.hamcrest.core.IsAnything +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ +import org.mockito.hamcrest.MockitoHamcrest import test.SocialProviderSpec +import test.Helper.mock import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -42,7 +46,7 @@ abstract class OAuth1ProviderSpec extends SocialProviderSpec[OAuth1Info] { val c = context "throw a RuntimeException if the unsafe 1.0 specification should be used" in new WithApplication { implicit val req = FakeRequest(GET, "?" + Denied + "=") - c.oAuthService.use10a returns false + when(c.oAuthService.use10a).thenReturn(false) c.provider.authenticate() must throwA[RuntimeException] } } @@ -58,7 +62,7 @@ abstract class OAuth1ProviderSpec extends SocialProviderSpec[OAuth1Info] { "fail with an UnexpectedResponseException if request token cannot be retrieved" in new WithApplication { implicit val req = FakeRequest() - c.oAuthService.retrieveRequestToken(c.oAuthSettings.callbackURL) returns Future.failed(new Exception("")) + when(c.oAuthService.retrieveRequestToken(c.oAuthSettings.callbackURL)).thenReturn(Future.failed(new Exception(""))) failed[UnexpectedResponseException](c.provider.authenticate()) { case e => e.getMessage must startWith(ErrorRequestToken.format(c.provider.id, "")) @@ -69,12 +73,11 @@ abstract class OAuth1ProviderSpec extends SocialProviderSpec[OAuth1Info] { implicit val req = FakeRequest() val serializedTokenSecret = "my.serialized.token.secret" - c.oAuthService.retrieveRequestToken(c.oAuthSettings.callbackURL) returns Future.successful(c.oAuthInfo) - c.oAuthService.redirectUrl(any()) answers { _: Any => c.oAuthSettings.authorizationURL } - c.oAuthTokenSecretProvider.build(any())(any(), any()) returns Future.successful(c.oAuthTokenSecret) - c.oAuthTokenSecretProvider.publish(any(), any())(any()) answers { (a, _) => - a.asInstanceOf[Array[Any]](0).asInstanceOf[Result] - } + when(c.oAuthService.retrieveRequestToken(c.oAuthSettings.callbackURL)).thenReturn(Future.successful(c.oAuthInfo)) + when(c.oAuthService.redirectUrl(any())).thenAnswer(_ => c.oAuthSettings.authorizationURL) + when(c.oAuthTokenSecretProvider.build(any())(any(), any())).thenReturn(Future.successful(c.oAuthTokenSecret)) + // when(c.oAuthTokenSecretProvider.publish(any(), any())(any())).thenAnswer(_.getArguments.asInstanceOf[Array[Any]](0).asInstanceOf[Result]) + when(c.oAuthTokenSecretProvider.publish(any(), any())(any())).thenAnswer(_.getArgument(0).asInstanceOf[Result]) result(c.provider.authenticate()) { result => status(result) must equalTo(SEE_OTHER) @@ -90,10 +93,6 @@ abstract class OAuth1ProviderSpec extends SocialProviderSpec[OAuth1Info] { verifyCallbackURLResolution("callback-url", secure = false, "http://www.example.com/request-path/callback-url") } - "resolves relative redirectURLs before starting the flow over https" in new WithApplication { - verifyCallbackURLResolution("/callback-url", secure = true, "https://www.example.com/callback-url") - } - def verifyCallbackURLResolution(callbackURL: String, secure: Boolean, resolvedCallbackURL: String) = { implicit val req = FakeRequest[AnyContent]( method = GET, @@ -102,24 +101,30 @@ abstract class OAuth1ProviderSpec extends SocialProviderSpec[OAuth1Info] { body = AnyContentAsEmpty, secure = secure) - c.oAuthSettings.callbackURL returns callbackURL + when(c.oAuthSettings.callbackURL).thenReturn(callbackURL) + + when(c.oAuthService.retrieveRequestToken(any())(any())).thenReturn(Future.successful(c.oAuthInfo)) - c.oAuthService.retrieveRequestToken(any())(any()) returns Future.successful(c.oAuthInfo) - c.oAuthService.redirectUrl(c.oAuthInfo.token) returns c.oAuthSettings.authorizationURL - c.oAuthTokenSecretProvider.build(any())(any(), any()) returns Future.successful(c.oAuthTokenSecret) - c.oAuthTokenSecretProvider.publish(any(), any())(any()) answers { _: Any => Results.Redirect(c.oAuthSettings.authorizationURL) } + when(c.oAuthService.redirectUrl(c.oAuthInfo.token)).thenAnswer(_ => c.oAuthSettings.authorizationURL) + + when(c.oAuthTokenSecretProvider.build(any())(any(), any())).thenReturn(Future.successful(c.oAuthTokenSecret)) + when(c.oAuthTokenSecretProvider.publish(any(), any())(any())).thenAnswer(_ => Results.Redirect(c.oAuthSettings.authorizationURL)) await(c.provider.authenticate()) - there was one(c.oAuthService).retrieveRequestToken(resolvedCallbackURL) + verify(c.oAuthService).retrieveRequestToken(resolvedCallbackURL) + } + + "resolves relative redirectURLs before starting the flow over https" in new WithApplication { + verifyCallbackURLResolution("/callback-url", secure = true, "https://www.example.com/callback-url") } "fail with an UnexpectedResponseException if access token cannot be retrieved" in new WithApplication { val tokenSecret = "my.token.secret" implicit val req = FakeRequest(GET, "?" + OAuthVerifier + "=my.verifier&" + OAuthToken + "=my.token") - c.oAuthTokenSecret.value returns tokenSecret - c.oAuthTokenSecretProvider.retrieve(any(), any()) returns Future.successful(c.oAuthTokenSecret) - c.oAuthService.retrieveAccessToken(c.oAuthInfo.copy(secret = tokenSecret), "my.verifier") returns Future.failed(new Exception("")) + when(c.oAuthTokenSecret.value).thenReturn(tokenSecret) + when(c.oAuthTokenSecretProvider.retrieve(any(), any())).thenReturn(Future.successful(c.oAuthTokenSecret)) + when(c.oAuthService.retrieveAccessToken(c.oAuthInfo.copy(secret = tokenSecret), "my.verifier")).thenReturn(Future.failed(new Exception(""))) failed[UnexpectedResponseException](c.provider.authenticate()) { case e => e.getMessage must startWith(ErrorAccessToken.format(c.provider.id, "")) @@ -130,9 +135,9 @@ abstract class OAuth1ProviderSpec extends SocialProviderSpec[OAuth1Info] { val tokenSecret = "my.token.secret" implicit val req = FakeRequest(GET, "?" + OAuthVerifier + "=my.verifier&" + OAuthToken + "=my.token") - c.oAuthTokenSecret.value returns tokenSecret - c.oAuthTokenSecretProvider.retrieve(any(), any()) returns Future.successful(c.oAuthTokenSecret) - c.oAuthService.retrieveAccessToken(c.oAuthInfo.copy(secret = tokenSecret), "my.verifier") returns Future.successful(c.oAuthInfo) + when(c.oAuthTokenSecret.value).thenReturn(tokenSecret) + when(c.oAuthTokenSecretProvider.retrieve(any(), any())).thenReturn(Future.successful(c.oAuthTokenSecret)) + when(c.oAuthService.retrieveAccessToken(c.oAuthInfo.copy(secret = tokenSecret), "my.verifier")).thenReturn(Future.successful(c.oAuthInfo)) authInfo(c.provider.authenticate())(_ must be equalTo c.oAuthInfo) } @@ -156,7 +161,7 @@ abstract class OAuth1ProviderSpec extends SocialProviderSpec[OAuth1Info] { /** * Context for the OAuth1ProviderSpec. */ -trait OAuth1ProviderSpecContext extends Scope with Mockito with ThrownExpectations { +trait OAuth1ProviderSpecContext extends Scope with ThrownExpectations { abstract class TestSecret extends OAuth1TokenSecret abstract class TestStateProvider extends OAuth1TokenSecretProvider { @@ -168,7 +173,7 @@ trait OAuth1ProviderSpecContext extends Scope with Mockito with ThrownExpectatio */ lazy val httpLayer = { val m = mock[MockHTTPLayer] - m.executionContext returns global + when(m.executionContext).thenReturn(global) m } @@ -181,10 +186,11 @@ trait OAuth1ProviderSpecContext extends Scope with Mockito with ThrownExpectatio * The OAuth1 service mock. */ lazy val oAuthService: OAuth1Service = { + val s = mock[PlayOAuth1Service] - s.use10a returns true - s.withSettings(anyFunction1) returns s - s.redirectUrl(anyString) returns "TESTING" + when(s.use10a).thenReturn(true) + when(s.withSettings(MockitoHamcrest.argThat(new IsAnything[OAuth1Settings => OAuth1Settings]))).thenReturn(s) + when(s.redirectUrl(anyString)).thenReturn("TESTING") s } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth2ProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth2ProviderSpec.scala index ed449fd2..905bbdac 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth2ProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OAuth2ProviderSpec.scala @@ -24,13 +24,15 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.OAuth2Provid import io.github.honeycombcheesecake.play.silhouette.impl.providers.state.UserStateItem import io.github.honeycombcheesecake.play.silhouette.helpers.Transform._ import org.specs2.matcher.ThrownExpectations -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.libs.json.{ JsValue, Json } import play.api.mvc.{ AnyContent, AnyContentAsEmpty, Result } import play.api.test.{ FakeHeaders, FakeRequest, WithApplication } import play.mvc.Http.HeaderNames import test.SocialStateProviderSpec +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ +import test.Helper.{ mockSmart, mock } import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.{ ExecutionContext, Future } @@ -65,10 +67,10 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So case Some(_) => implicit val req = FakeRequest(GET, "/") - c.stateProvider.serialize(c.state) returns "session-value" - c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.state(any[ExecutionContext]) returns Future.successful(c.state) - c.oAuthSettings.authorizationURL returns None + when(c.stateProvider.serialize(c.state)).thenReturn("session-value") + when(c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.oAuthSettings.authorizationURL).thenReturn(None) failed[ConfigurationException](c.provider.authenticate()) { case e => e.getMessage must startWith(AuthorizationURLUndefined.format(c.provider.id)) @@ -84,12 +86,12 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So val sessionKey = "session-key" val sessionValue = "session-value" - c.stateProvider.serialize(c.state) returns sessionValue - c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.state(any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.publish(any, any)(any) answers { (a, _) => - val result = a.asInstanceOf[Array[Any]](0).asInstanceOf[Result] - val state = a.asInstanceOf[Array[Any]](1).asInstanceOf[c.TestState] + when(c.stateProvider.serialize(c.state)).thenReturn(sessionValue) + when(c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.publish(any, any)(any)).thenAnswer { m => + val result = m.getArgument(0).asInstanceOf[Result] + val state = m.getArgument(1).asInstanceOf[c.TestState] result.withSession(sessionKey -> c.stateProvider.serialize(state)) } @@ -159,13 +161,13 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So val sessionKey = "session-key" val sessionValue = "session-value" - c.oAuthSettings.redirectURL returns Some(redirectURL) + when(c.oAuthSettings.redirectURL).thenReturn(Some(redirectURL)) - c.stateProvider.serialize(c.state) returns sessionValue - c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.state(any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.publish(any, any)(any) answers { (a, _) => - val result = a.asInstanceOf[Array[Any]](0).asInstanceOf[Result] + when(c.stateProvider.serialize(c.state)).thenReturn(sessionValue) + when(c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.publish(any, any)(any)).thenAnswer { m => + val result = m.getArgument(0).asInstanceOf[Result] result.withSession(sessionKey -> c.stateProvider.serialize(c.state)) } @@ -192,13 +194,13 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So val sessionKey = "session-key" val sessionValue = "session-value" - c.oAuthSettings.redirectURL returns redirectURL + when(c.oAuthSettings.redirectURL).thenReturn(redirectURL) - c.stateProvider.serialize(c.state) returns sessionValue - c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.state(any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.publish(any, any)(any) answers { (a, _) => - val result = a.asInstanceOf[Array[Any]](0).asInstanceOf[Result] + when(c.stateProvider.serialize(c.state)).thenReturn(sessionValue) + when(c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.publish(any, any)(any)).thenAnswer { m => + val result = m.getArgument(0).asInstanceOf[Result] result.withSession(sessionKey -> c.stateProvider.serialize(c.state)) } @@ -226,11 +228,11 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So case Some(_) => implicit val req = FakeRequest(GET, "/") - c.stateProvider.serialize(c.state) returns "" - c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.state(any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.publish(any, any)(any) answers { (a, _) => - a.asInstanceOf[Array[Any]](0).asInstanceOf[Result] + when(c.stateProvider.serialize(c.state)).thenReturn("") + when(c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.publish(any, any)(any)).thenAnswer { m => + m.getArgument(0).asInstanceOf[Result] } result(c.provider.authenticate())(result => @@ -251,23 +253,23 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So GrantType -> Seq(AuthorizationCode), Code -> Seq("my.code")) ++ c.oAuthSettings.accessTokenParams.transformValues(Seq(_)) ++ redirectParam.toMap.transformValues(Seq(_)) implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsRequest.withHttpHeaders(any) returns wsRequest + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) // We must use this neat trick here because it isn't possible to check the post call with a verification, // because of the implicit params needed for the post call. On the other hand we can test it in the abstract // spec, because we throw an exception in both cases which stops the test once the post method was called. // This protects as for an NPE because of the not mocked dependencies. The other solution would be to execute // this test in every provider with the full mocked dependencies. - wsRequest.post[Map[String, Seq[String]]](any)(any) answers { (a, _) => - if (a.asInstanceOf[Array[Any]](0).asInstanceOf[Map[String, Seq[String]]].equals(params)) { + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenAnswer { m => + if (m.getArgument(0).asInstanceOf[Map[String, Seq[String]]].equals(params)) { throw new RuntimeException("success") } else { throw new RuntimeException("failure") } } - c.httpLayer.url(c.oAuthSettings.accessTokenURL) returns wsRequest - c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.state(any[ExecutionContext]) returns Future.successful(c.state) + when(c.httpLayer.url(c.oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(c.state)) failed[RuntimeException](c.provider.authenticate()) { case e => e.getMessage must startWith("success") @@ -279,14 +281,14 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json throws new RuntimeException("Unexpected character ('<' (code 60))") - wsResponse.body returns "" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - c.httpLayer.url(c.oAuthSettings.accessTokenURL) returns wsRequest - c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(c.state) - c.stateProvider.state(any[ExecutionContext]) returns Future.successful(c.state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenThrow(new RuntimeException("Unexpected character ('<' (code 60))")) + when(wsResponse.body).thenReturn("") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(c.httpLayer.url(c.oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(c.stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(c.state)) + when(c.stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(c.state)) failed[UnexpectedResponseException](c.provider.authenticate()) { case e => e.getMessage must startWith( @@ -313,7 +315,7 @@ abstract class OAuth2ProviderSpec extends SocialStateProviderSpec[OAuth2Info, So /** * Context for the OAuth2ProviderSpec. */ -trait OAuth2ProviderSpecContext extends Scope with Mockito with ThrownExpectations { +trait OAuth2ProviderSpecContext extends Scope with ThrownExpectations { abstract class TestState extends SocialState(Set.empty) abstract class TestStateProvider extends SocialStateHandler { @@ -326,8 +328,8 @@ trait OAuth2ProviderSpecContext extends Scope with Mockito with ThrownExpectatio * The HTTP layer mock. */ lazy val httpLayer = { - val m = mock[MockHTTPLayer].smart - m.executionContext returns global + val m = mockSmart[MockHTTPLayer] + when(m.executionContext).thenReturn(global) m } @@ -343,7 +345,7 @@ trait OAuth2ProviderSpecContext extends Scope with Mockito with ThrownExpectatio /** * The OAuth2 state. */ - lazy val state = mock[TestState].smart + lazy val state = mockSmart[TestState] /** * A user state item. @@ -353,7 +355,7 @@ trait OAuth2ProviderSpecContext extends Scope with Mockito with ThrownExpectatio /** * The OAuth2 state provider. */ - lazy val stateProvider = mock[TestStateProvider].smart + lazy val stateProvider = mockSmart[TestStateProvider] /** * The stateful auth info. diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OpenIDProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OpenIDProviderSpec.scala index 4b862d88..6269deec 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OpenIDProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/OpenIDProviderSpec.scala @@ -19,12 +19,15 @@ import io.github.honeycombcheesecake.play.silhouette.api.util.HTTPLayer import io.github.honeycombcheesecake.play.silhouette.impl.exceptions.UnexpectedResponseException import io.github.honeycombcheesecake.play.silhouette.impl.providers.OpenIDProvider._ import org.specs2.matcher.ThrownExpectations -import org.specs2.mock.Mockito import org.specs2.specification.Scope +import org.mockito.ArgumentMatchers.any +import org.mockito.Mockito._ +import org.mockito.ArgumentCaptor import play.api.mvc.{ AnyContent, AnyContentAsEmpty } import play.api.test.{ FakeHeaders, FakeRequest, WithApplication } import play.mvc.Http.HeaderNames import test.SocialProviderSpec +import test.Helper.mock import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -42,7 +45,7 @@ abstract class OpenIDProviderSpec extends SocialProviderSpec[OpenIDInfo] { "fail with an UnexpectedResponseException if redirect URL couldn't be retrieved" in new WithApplication { implicit val req = FakeRequest() - c.openIDService.redirectURL(any(), any())(any()) returns Future.failed(new Exception("")) + when(c.openIDService.redirectURL(any(), any())(any())).thenReturn(Future.failed(new Exception(""))) failed[UnexpectedResponseException](c.provider.authenticate()) { case e => e.getMessage must startWith(ErrorRedirectURL.format(c.provider.id, "")) @@ -51,7 +54,8 @@ abstract class OpenIDProviderSpec extends SocialProviderSpec[OpenIDInfo] { "redirect to provider by using the provider URL" in new WithApplication { implicit val req = FakeRequest() - c.openIDService.redirectURL(any(), any())(any()) answers { _: Any => Future.successful(c.openIDSettings.providerURL) } + + when(c.openIDService.redirectURL(any(), any())(any())).thenAnswer(_ => Future.successful(c.openIDSettings.providerURL)) result(c.provider.authenticate()) { result => status(result) must equalTo(SEE_OTHER) @@ -61,7 +65,8 @@ abstract class OpenIDProviderSpec extends SocialProviderSpec[OpenIDInfo] { "redirect to provider by using a openID" in new WithApplication { implicit val req = FakeRequest(GET, "?openID=my.open.id") - c.openIDService.redirectURL(any(), any())(any()) answers { _: Any => Future.successful(c.openIDSettings.providerURL) } + + when(c.openIDService.redirectURL(any(), any())(any())).thenAnswer(_ => Future.successful(c.openIDSettings.providerURL)) result(c.provider.authenticate()) { result => status(result) must equalTo(SEE_OTHER) @@ -89,16 +94,19 @@ abstract class OpenIDProviderSpec extends SocialProviderSpec[OpenIDInfo] { body = AnyContentAsEmpty, secure = secure) - c.openIDSettings.callbackURL returns callbackURL - c.openIDService.redirectURL(any(), any())(any()) answers { _: Any => Future.successful(c.openIDSettings.providerURL) } + when(c.openIDSettings.callbackURL).thenReturn(callbackURL) + when(c.openIDService.redirectURL(any(), any())(any())).thenAnswer(_ => Future.successful(c.openIDSettings.providerURL)) await(c.provider.authenticate()) - there was one(c.openIDService).redirectURL(any(), ===(resolvedCallbackURL))(any()) + + val argument = ArgumentCaptor.forClass(classOf[String]) + verify(c.openIDService).redirectURL(any(), argument.capture())(any()) + assert(argument.getValue() === resolvedCallbackURL) } "fail with an UnexpectedResponseException if auth info cannot be retrieved" in new WithApplication { implicit val req = FakeRequest(GET, "?" + Mode + "=id_res") - c.openIDService.verifiedID(any(), any()) returns Future.failed(new Exception("")) + when(c.openIDService.verifiedID(any(), any())).thenReturn(Future.failed(new Exception(""))) failed[UnexpectedResponseException](c.provider.authenticate()) { case e => e.getMessage must startWith(ErrorVerification.format(c.provider.id, "")) @@ -107,7 +115,7 @@ abstract class OpenIDProviderSpec extends SocialProviderSpec[OpenIDInfo] { "return the auth info" in new WithApplication { implicit val req = FakeRequest(GET, "?" + Mode + "=id_res") - c.openIDService.verifiedID(any(), any()) answers { _: Any => Future.successful(c.openIDInfo) } + when(c.openIDService.verifiedID(any(), any())).thenAnswer(_ => Future.successful(c.openIDInfo)) authInfo(c.provider.authenticate())(_ must be equalTo c.openIDInfo) } @@ -131,14 +139,14 @@ abstract class OpenIDProviderSpec extends SocialProviderSpec[OpenIDInfo] { /** * Context for the OpenIDProviderSpec. */ -trait OpenIDProviderSpecContext extends Scope with Mockito with ThrownExpectations { +trait OpenIDProviderSpecContext extends Scope with ThrownExpectations { /** * The HTTP layer mock. */ lazy val httpLayer = { val m = mock[HTTPLayer] - m.executionContext returns global + when(m.executionContext).thenReturn(global) m } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/PasswordProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/PasswordProviderSpec.scala index 07bd244f..6f4fe2d5 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/PasswordProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/PasswordProviderSpec.scala @@ -17,14 +17,16 @@ package io.github.honeycombcheesecake.play.silhouette.impl.providers import io.github.honeycombcheesecake.play.silhouette.api.repositories.AuthInfoRepository import io.github.honeycombcheesecake.play.silhouette.api.util._ -import org.specs2.mock.Mockito import org.specs2.specification.Scope +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mock import play.api.test.PlaySpecification /** * Abstract test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.providers.PasswordProvider]] based class. */ -trait PasswordProviderSpec extends PlaySpecification with Mockito { +trait PasswordProviderSpec extends PlaySpecification { /** * The context. @@ -59,11 +61,11 @@ trait PasswordProviderSpec extends PlaySpecification with Mockito { */ private def hasher(id: String) = { val h = mock[PasswordHasher] - h.id returns id - h.isSuitable(any()) answers { p: Any => - p.asInstanceOf[PasswordInfo].hasher == h.id + when(h.id).thenReturn(id) + when(h.isSuitable(any())).thenAnswer { p => + p.getArgument(0).asInstanceOf[PasswordInfo].hasher == h.id } - h.isDeprecated(any()) returns Some(false) + when(h.isDeprecated(any())).thenReturn(Some(false)) h } } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/SocialProviderRegistrySpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/SocialProviderRegistrySpec.scala index 607d665f..7b10feaf 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/SocialProviderRegistrySpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/SocialProviderRegistrySpec.scala @@ -18,14 +18,15 @@ package io.github.honeycombcheesecake.play.silhouette.impl.providers import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.TwitterProvider import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.{ GoogleProvider, FacebookProvider } import io.github.honeycombcheesecake.play.silhouette.impl.providers.openid.YahooProvider -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.test.PlaySpecification +import org.mockito.Mockito._ +import test.Helper.mock /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialProviderRegistry]] class. */ -class SocialProviderRegistrySpec extends PlaySpecification with Mockito { +class SocialProviderRegistrySpec extends PlaySpecification { "The `get` method" should { "return a provider by its type" in new Context { @@ -79,11 +80,11 @@ class SocialProviderRegistrySpec extends PlaySpecification with Mockito { */ val providers = { val facebook = mock[FacebookProvider] - facebook.id returns FacebookProvider.ID + when(facebook.id).thenReturn(FacebookProvider.ID) val google = mock[GoogleProvider] - google.id returns GoogleProvider.ID + when(google.id).thenReturn(GoogleProvider.ID) val twitter = mock[TwitterProvider] - twitter.id returns TwitterProvider.ID + when(twitter.id).thenReturn(TwitterProvider.ID) Seq( facebook, diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/custom/FacebookProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/custom/FacebookProviderSpec.scala index a936e4f7..ffc3172a 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/custom/FacebookProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/custom/FacebookProviderSpec.scala @@ -33,7 +33,7 @@ import scala.concurrent.{ ExecutionContext, Future } /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.FacebookProvider]] class which uses a custom social profile. */ -class FacebookProviderSpec extends OAuth2ProviderSpec { +class FacebookProviderSpec extends OAuth2ProviderSpec with org.specs2.mock.Mockito { "The `withSettings` method" should { "create a new instance with customized settings" in new WithApplication with Context { @@ -163,7 +163,7 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { /** * The OAuth2 settings. */ - override lazy val oAuthSettings = spy(OAuth2Settings( + override lazy val oAuthSettings = org.mockito.Mockito.spy(OAuth2Settings( authorizationURL = Some("https://graph.facebook.com/oauth/authorize"), accessTokenURL = "https://graph.facebook.com/oauth/access_token", redirectURL = Some("https://www.mohiva.com"), diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/LinkedInProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/LinkedInProviderSpec.scala index 583f5169..0dc7e66f 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/LinkedInProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/LinkedInProviderSpec.scala @@ -22,7 +22,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialProfil import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.LinkedInProvider._ import play.api.test.WithApplication +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any import test.Helper +import test.Helper.mock import scala.concurrent.Future @@ -39,7 +42,7 @@ class LinkedInProviderSpec extends OAuth1ProviderSpec { val s = provider.withSettings(overrideSettingsFunction) s.settings.requestTokenURL must be equalTo "new-request-token-url" - there was one(oAuthService).withSettings(overrideSettingsFunction) + verify(oAuthService).withSettings(overrideSettingsFunction) } } @@ -47,10 +50,10 @@ class LinkedInProviderSpec extends OAuth1ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/linkedin.error.json") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/linkedin.error.json")) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo)) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -66,10 +69,10 @@ class LinkedInProviderSpec extends OAuth1ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json throws new RuntimeException("") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo)) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -80,24 +83,24 @@ class LinkedInProviderSpec extends OAuth1ProviderSpec { val url = "https://custom.api.url" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/linkedin.success.json") - httpLayer.url(url) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/linkedin.success.json")) + when(httpLayer.url(url)).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo)) - there was one(httpLayer).url(url) + verify(httpLayer).url(url) } "return the social profile" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/linkedin.success.json") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/linkedin.success.json")) + when(httpLayer.url(API)).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo)) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/TwitterProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/TwitterProviderSpec.scala index a7dcf7fc..5b943df6 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/TwitterProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/TwitterProviderSpec.scala @@ -22,7 +22,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialProfil import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.TwitterProvider._ import play.api.test.WithApplication +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any import test.Helper +import test.Helper.mock import scala.concurrent.Future @@ -39,7 +42,7 @@ class TwitterProviderSpec extends OAuth1ProviderSpec { val s = provider.withSettings(overrideSettingsFunction) s.settings.requestTokenURL must be equalTo "new-request-token-url" - there was one(oAuthService).withSettings(overrideSettingsFunction) + verify(oAuthService).withSettings(overrideSettingsFunction) } } @@ -47,10 +50,10 @@ class TwitterProviderSpec extends OAuth1ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/twitter.error.json") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/twitter.error.json")) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo)) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -63,10 +66,10 @@ class TwitterProviderSpec extends OAuth1ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json throws new RuntimeException("") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo)) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -77,24 +80,24 @@ class TwitterProviderSpec extends OAuth1ProviderSpec { val url = "https://custom.api.url" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/twitter.with.email.json") - httpLayer.url(url) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/twitter.with.email.json")) + when(httpLayer.url(url)).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo)) - there was one(httpLayer).url(url) + verify(httpLayer).url(url) } "return the social profile" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/twitter.success.json") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/twitter.success.json")) + when(httpLayer.url(API)).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo)) { p => p must be equalTo CommonSocialProfile( @@ -107,10 +110,10 @@ class TwitterProviderSpec extends OAuth1ProviderSpec { "return the social profile with email" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/twitter.with.email.json") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/twitter.with.email.json")) + when(httpLayer.url(API)).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo)) { p => p must be equalTo CommonSocialProfile( @@ -137,7 +140,7 @@ class TwitterProviderSpec extends OAuth1ProviderSpec { /** * The OAuth1 settings. */ - override lazy val oAuthSettings = spy(OAuth1Settings( + override lazy val oAuthSettings = org.mockito.Mockito.spy(OAuth1Settings( requestTokenURL = "https://twitter.com/oauth/request_token", accessTokenURL = "https://twitter.com/oauth/access_token", authorizationURL = "https://twitter.com/oauth/authenticate", diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/XingProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/XingProviderSpec.scala index bfb7ce56..18c0b995 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/XingProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/XingProviderSpec.scala @@ -22,7 +22,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialProfil import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.XingProvider._ import play.api.test.WithApplication +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any import test.Helper +import test.Helper.mock import scala.concurrent.Future @@ -39,7 +42,7 @@ class XingProviderSpec extends OAuth1ProviderSpec { val s = provider.withSettings(overrideSettingsFunction) s.settings.requestTokenURL must be equalTo "new-request-token-url" - there was one(oAuthService).withSettings(overrideSettingsFunction) + verify(oAuthService).withSettings(overrideSettingsFunction) } } @@ -47,10 +50,10 @@ class XingProviderSpec extends OAuth1ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/xing.error.json") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/xing.error.json")) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo)) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -63,10 +66,10 @@ class XingProviderSpec extends OAuth1ProviderSpec { "throw ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json throws new RuntimeException("") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo)) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -77,24 +80,24 @@ class XingProviderSpec extends OAuth1ProviderSpec { val url = "https://custom.api.url" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/xing.success.json") - httpLayer.url(url) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/xing.success.json")) + when(httpLayer.url(url)).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo)) - there was one(httpLayer).url(url) + verify(httpLayer).url(url) } "return the social profile" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsRequest.sign(any) returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - wsResponse.json returns Helper.loadJson("providers/oauth1/xing.success.json") - httpLayer.url(API) returns wsRequest + when(wsRequest.sign(any)).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth1/xing.success.json")) + when(httpLayer.url(API)).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo)) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/secrets/CookieSecretSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/secrets/CookieSecretSpec.scala index 27d6826e..9f04b17a 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/secrets/CookieSecretSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/secrets/CookieSecretSpec.scala @@ -25,10 +25,12 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.secre import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.secrets.CookieSecretProvider._ import org.specs2.control.NoLanguageFeatures import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.mvc.{ Cookie, Results } import play.api.test.{ FakeRequest, PlaySpecification, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mockSmart import java.time.{ ZoneId, ZonedDateTime } import scala.concurrent.ExecutionContext.Implicits.global @@ -40,7 +42,7 @@ import scala.util.{ Failure, Success } /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.secrets.CookieSecret]] class. */ -class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers with NoLanguageFeatures { +class CookieSecretSpec extends PlaySpecification with JsonMatchers with NoLanguageFeatures { "The `isExpired` method of the secret" should { "return true if the secret is expired" in new Context { @@ -56,13 +58,13 @@ class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers "sign the cookie" in new WithApplication with Context { serialize(secret, signer, crypter) - there was one(signer).sign(any()) + verify(signer).sign(any()) } "encrypt the cookie" in new WithApplication with Context { serialize(secret, signer, crypter) - there was one(crypter).encrypt(any()) + verify(crypter).encrypt(any()) } } @@ -82,7 +84,7 @@ class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers } "throw an OAuth1TokenSecretException if a secret is badly signed" in new WithApplication with Context { - signer.extract(any()) returns Failure(new Exception("Bad signature")) + when(signer.extract(any())).thenReturn(Failure(new Exception("Bad signature"))) val value = serialize(secret, signer, crypter) val msg = Pattern.quote(InvalidCookieSignature) @@ -104,7 +106,7 @@ class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers implicit val req = FakeRequest() val dateTime = ZonedDateTime.of(2014, 8, 8, 0, 0, 0, 0, ZoneId.systemDefault) - clock.now returns dateTime + when(clock.now).thenReturn(dateTime) val s = await(provider.build(oAuthInfo)) @@ -149,7 +151,7 @@ class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers } "throw an OAuth1TokenSecretException if client secret is badly signed" in new WithApplication with Context { - signer.extract(any()) returns Failure(new Exception("Bad signature")) + when(signer.extract(any())).thenReturn(Failure(new Exception("Bad signature"))) implicit val req = FakeRequest().withCookies(Cookie(settings.cookieName, CookieSecret.serialize(secret, signer, crypter))) @@ -189,7 +191,7 @@ class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers /** * The clock implementation. */ - lazy val clock: Clock = mock[Clock].smart + lazy val clock: Clock = mockSmart[Clock] /** * The settings. @@ -205,9 +207,9 @@ class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers * none cookie values in a cookie. */ lazy val crypter = { - val c = mock[Crypter].smart - c.encrypt(any()) answers { p: Any => Base64.encode(p.asInstanceOf[String]) } - c.decrypt(any()) answers { p: Any => Base64.decode(p.asInstanceOf[String]) } + val c = mockSmart[Crypter] + when(c.encrypt(any())).thenAnswer(p => Base64.encode(p.getArgument(0).asInstanceOf[String])) + when(c.decrypt(any())).thenAnswer(p => Base64.decode(p.getArgument(0).asInstanceOf[String])) c } @@ -217,9 +219,9 @@ class CookieSecretSpec extends PlaySpecification with Mockito with JsonMatchers * The signer returns the same value as passed to the methods. This is enough for testing. */ lazy val signer = { - val c = mock[Signer].smart - c.sign(any()) answers { p: Any => p.asInstanceOf[String] } - c.extract(any()) answers { p: Any => Success(p.asInstanceOf[String]) } + val c = mockSmart[Signer] + when(c.sign(any())).thenAnswer(_.getArgument(0).asInstanceOf[String]) + when(c.extract(any())).thenAnswer(p => Success(p.getArgument(0).asInstanceOf[String])) c } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/services/PlayOAuth1ServiceSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/services/PlayOAuth1ServiceSpec.scala index 16233d04..7ff4abe9 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/services/PlayOAuth1ServiceSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth1/services/PlayOAuth1ServiceSpec.scala @@ -16,19 +16,19 @@ package io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth1.services import io.github.honeycombcheesecake.play.silhouette.impl.providers.{ OAuth1Info, OAuth1Settings } -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.libs.oauth.{ OAuth, RequestToken } import play.api.libs.ws.WSSignatureCalculator import play.api.test.{ PlaySpecification, WithApplication } import play.shaded.oauth.oauth.signpost.exception.{ OAuthException, OAuthMessageSignerException } +import org.mockito.Mockito._ import scala.concurrent.ExecutionContext.Implicits.global /** * Test case for the [[PlayOAuth1Service]] class. */ -class PlayOAuth1ServiceSpec extends PlaySpecification with Mockito { +class PlayOAuth1ServiceSpec extends PlaySpecification { "The `withSettings` method" should { "create a new instance with customized settings" in new WithApplication with Context { @@ -48,13 +48,13 @@ class PlayOAuth1ServiceSpec extends PlaySpecification with Mockito { "The `use10a` method" should { "return true if the safer 1.0a specification will be used" in new Context { - oauth.use10a returns true + when(oauth.use10a).thenReturn(true) service.use10a must beTrue } "return false if the unsafer 1.0 specification will be used" in new Context { - oauth.use10a returns false + when(oauth.use10a).thenReturn(false) service.use10a must beFalse } @@ -62,13 +62,13 @@ class PlayOAuth1ServiceSpec extends PlaySpecification with Mockito { "The `retrieveRequestToken` method" should { "throw exception if the token couldn't be retrieved" in new Context { - oauth.retrieveRequestToken(settings.callbackURL) returns Left(new OAuthMessageSignerException("")) + when(oauth.retrieveRequestToken(settings.callbackURL)).thenReturn(Left(new OAuthMessageSignerException(""))) await(service.retrieveRequestToken(settings.callbackURL)) must throwA[OAuthException] } "return request token" in new Context { - oauth.retrieveRequestToken(settings.callbackURL) returns Right(token) + when(oauth.retrieveRequestToken(settings.callbackURL)).thenReturn(Right(token)) await(service.retrieveRequestToken(settings.callbackURL)) must be equalTo info } @@ -76,13 +76,13 @@ class PlayOAuth1ServiceSpec extends PlaySpecification with Mockito { "The `retrieveAccessToken` method" should { "throw Exception if the token couldn't be retrieved" in new Context { - oauth.retrieveAccessToken(token, "") returns Left(new OAuthMessageSignerException("")) + when(oauth.retrieveAccessToken(token, "")).thenReturn(Left(new OAuthMessageSignerException(""))) await(service.retrieveAccessToken(info, "")) must throwA[OAuthException] } "return access token" in new Context { - oauth.retrieveAccessToken(token, "") returns Right(token) + when(oauth.retrieveAccessToken(token, "")).thenReturn(Right(token)) await(service.retrieveAccessToken(info, "")) must be equalTo info } @@ -90,7 +90,7 @@ class PlayOAuth1ServiceSpec extends PlaySpecification with Mockito { "The `redirectUrl` method" should { "return the redirect Url" in new Context { - oauth.redirectUrl("token") returns "http://redirect.url" + when(oauth.redirectUrl("token")).thenReturn("http://redirect.url") service.redirectUrl("token") must be equalTo "http://redirect.url" } @@ -98,7 +98,7 @@ class PlayOAuth1ServiceSpec extends PlaySpecification with Mockito { "The `sign` method" should { "return the signature calculator" in new Context { - oauth.info returns PlayOAuth1Service.serviceInfo(settings) + when(oauth.info).thenReturn(PlayOAuth1Service.serviceInfo(settings)) service.sign(info) must beAnInstanceOf[WSSignatureCalculator] } @@ -133,7 +133,7 @@ class PlayOAuth1ServiceSpec extends PlaySpecification with Mockito { /** * A mock of the Play Framework OAuth implementation. */ - lazy val oauth: OAuth = mock[OAuth] + lazy val oauth: OAuth = mock(classOf[OAuth]) /** * The service to test. diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/Auth0ProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/Auth0ProviderSpec.scala index a3085bb4..799f9b3a 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/Auth0ProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/Auth0ProviderSpec.scala @@ -23,7 +23,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.Auth0Provider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -47,13 +50,13 @@ class Auth0ProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class Auth0ProviderSpec extends OAuth2ProviderSpec { val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -83,13 +86,13 @@ class Auth0ProviderSpec extends OAuth2ProviderSpec { val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -100,15 +103,15 @@ class Auth0ProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -119,10 +122,10 @@ class Auth0ProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 400 - wsRequest.get() returns Future.successful(wsResponse) - wsRequest.withHttpHeaders(("Authorization", s"Bearer ${oAuthInfoObject.accessToken}")) returns wsRequest - httpLayer.url(oAuthSettings.apiURL.get) returns wsRequest + when(wsResponse.status).thenReturn(400) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsRequest.withHttpHeaders(("Authorization", s"Bearer ${oAuthInfoObject.accessToken}"))).thenReturn(wsRequest) + when(httpLayer.url(oAuthSettings.apiURL.get)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfoObject)) { case e => e.getMessage must equalTo(GenericHttpStatusProfileError.format(provider.id, 400)) @@ -133,11 +136,11 @@ class Auth0ProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - wsRequest.withHttpHeaders(("Authorization", s"Bearer ${oAuthInfoObject.accessToken}")) returns wsRequest - httpLayer.url(oAuthSettings.apiURL.get) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsRequest.withHttpHeaders(("Authorization", s"Bearer ${oAuthInfoObject.accessToken}"))).thenReturn(wsRequest) + when(httpLayer.url(oAuthSettings.apiURL.get)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo("[Silhouette][auth0] error retrieving profile information") @@ -149,11 +152,11 @@ class Auth0ProviderSpec extends OAuth2ProviderSpec { val wsResponse = mock[MockWSRequest#Response] val userProfile = Helper.loadJson(Auth0UserProfileJson) - wsResponse.status returns 200 - wsResponse.json returns userProfile - wsRequest.get() returns Future.successful(wsResponse) - wsRequest.withHttpHeaders(("Authorization", s"Bearer ${oAuthInfoObject.accessToken}")) returns wsRequest - httpLayer.url(oAuthSettings.apiURL.get) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(userProfile) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(wsRequest.withHttpHeaders(("Authorization", s"Bearer ${oAuthInfoObject.accessToken}"))).thenReturn(wsRequest) + when(httpLayer.url(oAuthSettings.apiURL.get)).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/DropboxProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/DropboxProviderSpec.scala index 4bb32659..e5d608a5 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/DropboxProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/DropboxProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.DropboxProvider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class DropboxProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class DropboxProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class DropboxProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class DropboxProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -118,11 +121,11 @@ class DropboxProviderSpec extends OAuth2ProviderSpec { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.json returns Helper.loadJson("providers/oauth2/dropbox.error.json") - wsResponse.status returns 400 - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/dropbox.error.json")) + when(wsResponse.status).thenReturn(400) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(authInfo)) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -136,11 +139,11 @@ class DropboxProviderSpec extends OAuth2ProviderSpec { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(authInfo)) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -152,27 +155,27 @@ class DropboxProviderSpec extends OAuth2ProviderSpec { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/dropbox.success.json") - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/dropbox.success.json")) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url)).thenReturn(wsRequest) await(provider.retrieveProfile(authInfo)) - there was one(httpLayer).url(url) + verify(httpLayer).url(url) } "return the social profile" in new WithApplication with Context { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/dropbox.success.json") - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/dropbox.success.json")) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(authInfo)) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FacebookProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FacebookProviderSpec.scala index fa7afd47..34614f0c 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FacebookProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FacebookProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.FacebookProvider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -117,10 +120,10 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 400 - wsResponse.json returns Helper.loadJson("providers/oauth2/facebook.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(400) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/facebook.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -134,10 +137,10 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -148,24 +151,24 @@ class FacebookProviderSpec extends OAuth2ProviderSpec { val url = "https://custom.api.url?access_token=%s" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/facebook.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url.format("my.access.token")) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/facebook.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url.format("my.access.token"))).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) - there was one(httpLayer).url(url.format("my.access.token")) + verify(httpLayer).url(url.format("my.access.token")) } "return the social profile" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/facebook.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/facebook.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FoursquareProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FoursquareProviderSpec.scala index 5de7441f..6cb205d4 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FoursquareProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/FoursquareProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.FoursquareProvider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -117,10 +120,10 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 400 - wsResponse.json returns Helper.loadJson("providers/oauth2/foursquare.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token", DefaultAPIVersion)) returns wsRequest + when(wsResponse.status).thenReturn(400) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/foursquare.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token", DefaultAPIVersion))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -134,10 +137,10 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token", DefaultAPIVersion)) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token", DefaultAPIVersion))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -148,24 +151,24 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { val url = "https://custom.api.url?access_token=%s" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/foursquare.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url.format("my.access.token")) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/foursquare.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url.format("my.access.token"))).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) - there was one(httpLayer).url(url.format("my.access.token")) + verify(httpLayer).url(url.format("my.access.token")) } "return the social profile" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/foursquare.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token", DefaultAPIVersion)) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/foursquare.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token", DefaultAPIVersion))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -180,10 +183,10 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { "return the social profile if API is deprecated" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/foursquare.deprecated.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token", DefaultAPIVersion)) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/foursquare.deprecated.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token", DefaultAPIVersion))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -200,10 +203,10 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/foursquare.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token", "20120101")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/foursquare.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token", "20120101"))).thenReturn(wsRequest) profile(provider.withSettings(_.copy(customProperties = customProperties)) .retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => @@ -221,10 +224,10 @@ class FoursquareProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/foursquare.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token", DefaultAPIVersion)) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/foursquare.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token", DefaultAPIVersion))).thenReturn(wsRequest) profile(provider.withSettings(_.copy(customProperties = customProperties)) .retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitHubProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitHubProviderSpec.scala index 925dad52..86ee22a4 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitHubProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitHubProviderSpec.scala @@ -25,7 +25,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.GitHu import play.api.http.HeaderNames import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -49,13 +52,13 @@ class GitHubProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(HeaderNames.ACCEPT -> "application/json") returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(HeaderNames.ACCEPT -> "application/json")).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -66,13 +69,13 @@ class GitHubProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(HeaderNames.ACCEPT -> "application/json") returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(HeaderNames.ACCEPT -> "application/json")).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -83,13 +86,13 @@ class GitHubProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -100,15 +103,15 @@ class GitHubProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -119,11 +122,11 @@ class GitHubProviderSpec extends OAuth2ProviderSpec { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 400 - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsResponse.json returns Helper.loadJson("providers/oauth2/github.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API) returns wsRequest + when(wsResponse.status).thenReturn(400) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/github.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(authInfo)) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -137,11 +140,11 @@ class GitHubProviderSpec extends OAuth2ProviderSpec { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API)).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(authInfo)) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -153,27 +156,27 @@ class GitHubProviderSpec extends OAuth2ProviderSpec { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/github.success.json") - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/github.success.json")) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url)).thenReturn(wsRequest) await(provider.retrieveProfile(authInfo)) - there was one(httpLayer).url(url) + verify(httpLayer).url(url) } "return the social profile" in new WithApplication with Context { val authInfo = oAuthInfo.as[OAuth2Info] val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/github.success.json") - wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}") returns wsRequest - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/github.success.json")) + when(wsRequest.withHttpHeaders(AUTHORIZATION -> s"Bearer ${authInfo.accessToken}")).thenReturn(wsRequest) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API)).thenReturn(wsRequest) profile(provider.retrieveProfile(authInfo)) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitLabProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitLabProviderSpec.scala index 0beb19b1..4398710a 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitLabProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GitLabProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.GitLabProvider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class GitLabProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class GitLabProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class GitLabProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class GitLabProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -117,10 +120,10 @@ class GitLabProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 400 - wsResponse.json returns Helper.loadJson("providers/oauth2/gitlab.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(400) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/gitlab.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -132,10 +135,10 @@ class GitLabProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -146,24 +149,24 @@ class GitLabProviderSpec extends OAuth2ProviderSpec { val url = "https://custom.api.url?access_token=%s" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/gitlab.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url.format("my.access.token")) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/gitlab.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url.format("my.access.token"))).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) - there was one(httpLayer).url(url.format("my.access.token")) + verify(httpLayer).url(url.format("my.access.token")) } "return the social profile" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/gitlab.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/gitlab.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GoogleProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GoogleProviderSpec.scala index c316e9b8..f2b1cd04 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GoogleProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/GoogleProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.GoogleProvider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -117,10 +120,10 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 401 - wsResponse.json returns Helper.loadJson("providers/oauth2/google.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(401) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/google.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -133,10 +136,10 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns missing People API config" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 403 - wsResponse.json returns Helper.loadJson("providers/oauth2/google.error.api.missing.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(403) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/google.error.api.missing.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) val apiErrMsg = "People API has not been used in project 1234567890 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/people.googleapis.com/overview?project=1234567890 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry." @@ -151,10 +154,10 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -165,24 +168,24 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { val url = "https://custom.api.url?access_token=%s" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/google.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url.format("my.access.token")) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/google.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url.format("my.access.token"))).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) - there was one(httpLayer).url(url.format("my.access.token")) + verify(httpLayer).url(url.format("my.access.token")) } "return the social profile with an email" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/google.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/google.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -198,10 +201,10 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { "return the social profile without an email" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/google.without.email.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/google.without.email.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -216,10 +219,10 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { "return the social profile with an avatar url" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/google.img.non-default.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/google.img.non-default.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -234,10 +237,10 @@ class GoogleProviderSpec extends OAuth2ProviderSpec { "return the social profile without an avatar url" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/google.img.default.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/google.img.default.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/InstagramProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/InstagramProviderSpec.scala index 85c2d4ac..1d0a1605 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/InstagramProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/InstagramProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.InstagramProvider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class InstagramProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class InstagramProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class InstagramProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class InstagramProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -117,10 +120,10 @@ class InstagramProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 400 - wsResponse.json returns Helper.loadJson("providers/oauth2/instagram.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(400) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/instagram.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -134,10 +137,10 @@ class InstagramProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -148,24 +151,24 @@ class InstagramProviderSpec extends OAuth2ProviderSpec { val url = "https://custom.api.url?access_token=%s" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/instagram.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url.format("my.access.token")) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/instagram.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url.format("my.access.token"))).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) - there was one(httpLayer).url(url.format("my.access.token")) + verify(httpLayer).url(url.format("my.access.token")) } "return the social profile" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/instagram.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/instagram.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/LinkedInProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/LinkedInProviderSpec.scala index 08b5a8f8..cecef089 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/LinkedInProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/LinkedInProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.LinkedInProvider._ import play.api.libs.json.Json import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -117,10 +120,10 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 401 - wsResponse.json returns Helper.loadJson("providers/oauth2/linkedin.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(401) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/linkedin.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) mockEmailAndPhoto(httpLayer) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -136,10 +139,10 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) mockEmailAndPhoto(httpLayer) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -150,32 +153,32 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { val url = "https://custom.api.url?access_token=%s" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/linkedin.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url.format("my.access.token")) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/linkedin.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url.format("my.access.token"))).thenReturn(wsRequest) mockEmailAndPhoto(httpLayer) await(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) - there was one(httpLayer).url(url.format("my.access.token")) + verify(httpLayer).url(url.format("my.access.token")) } def mockEmailAndPhoto(httpLayer: MockHTTPLayer) = { // Email val wsRequestEmail = mock[MockWSRequest] val wsResponseEmail = mock[MockWSRequest#Response] - wsResponseEmail.status returns 200 - wsResponseEmail.json returns Helper.loadJson("providers/oauth2/linkedin.email.json") - wsRequestEmail.get() returns Future.successful(wsResponseEmail) - httpLayer.url(EMAIL.format("my.access.token")) returns wsRequestEmail + when(wsResponseEmail.status).thenReturn(200) + when(wsResponseEmail.json).thenReturn(Helper.loadJson("providers/oauth2/linkedin.email.json")) + when(wsRequestEmail.get()).thenReturn(Future.successful(wsResponseEmail)) + when(httpLayer.url(EMAIL.format("my.access.token"))).thenReturn(wsRequestEmail) // Photo val wsRequestPhoto = mock[MockWSRequest] val wsResponsePhoto = mock[MockWSRequest#Response] - wsResponsePhoto.status returns 200 - wsResponsePhoto.json returns Helper.loadJson("providers/oauth2/linkedin.photo.json") - wsRequestPhoto.get() returns Future.successful(wsResponsePhoto) - httpLayer.url(PHOTO.format("my.access.token")) returns wsRequestPhoto + when(wsResponsePhoto.status).thenReturn(200) + when(wsResponsePhoto.json).thenReturn(Helper.loadJson("providers/oauth2/linkedin.photo.json")) + when(wsRequestPhoto.get()).thenReturn(Future.successful(wsResponsePhoto)) + when(httpLayer.url(PHOTO.format("my.access.token"))).thenReturn(wsRequestPhoto) } @@ -183,10 +186,10 @@ class LinkedInProviderSpec extends OAuth2ProviderSpec { // Basic profile val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/linkedin.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/linkedin.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) mockEmailAndPhoto(httpLayer) diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/VKProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/VKProviderSpec.scala index 3f86af8c..98c1e0ea 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/VKProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/oauth2/VKProviderSpec.scala @@ -24,7 +24,10 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import io.github.honeycombcheesecake.play.silhouette.impl.providers.oauth2.VKProvider._ import play.api.libs.json.{ JsObject, Json } import play.api.test.{ FakeRequest, WithApplication } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers._ import test.Helper +import test.Helper.mock import scala.concurrent.{ ExecutionContext, Future } @@ -48,13 +51,13 @@ class VKProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 401 - wsResponse.body returns "Unauthorized" - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(401) + when(wsResponse.body).thenReturn("Unauthorized") + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(UnexpectedResponse.format(provider.id, "Unauthorized", 401)) @@ -65,13 +68,13 @@ class VKProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns Json.obj() - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Json.obj()) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) failed[UnexpectedResponseException](provider.authenticate()) { case e => e.getMessage must startWith(InvalidInfoFormat.format(provider.id, "")) @@ -82,13 +85,13 @@ class VKProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) authInfo(provider.authenticate())(_ must be equalTo oAuthInfo.as[OAuth2Info]) } @@ -99,15 +102,15 @@ class VKProviderSpec extends OAuth2ProviderSpec { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] implicit val req = FakeRequest(GET, "?" + Code + "=my.code") - wsResponse.status returns 200 - wsResponse.json returns oAuthInfo - wsRequest.withHttpHeaders(any) returns wsRequest - wsRequest.post[Map[String, Seq[String]]](any)(any) returns Future.successful(wsResponse) - httpLayer.url(oAuthSettings.accessTokenURL) returns wsRequest - stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext]) returns Future.successful(state) - stateProvider.state(any[ExecutionContext]) returns Future.successful(state) - stateProvider.withHandler(any[SocialStateItemHandler]) returns stateProvider - state.items returns Set(userStateItem) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(oAuthInfo) + when(wsRequest.withHttpHeaders(any)).thenReturn(wsRequest) + when(wsRequest.post[Map[String, Seq[String]]](any)(any)).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(oAuthSettings.accessTokenURL)).thenReturn(wsRequest) + when(stateProvider.unserialize(anyString)(any[ExtractableRequest[String]], any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.state(any[ExecutionContext])).thenReturn(Future.successful(state)) + when(stateProvider.withHandler(any[SocialStateItemHandler])).thenReturn(stateProvider) + when(state.items).thenReturn(Set(userStateItem)) statefulAuthInfo(provider.authenticate(userStateItem))(_ must be equalTo stateAuthInfo) } @@ -117,10 +120,10 @@ class VKProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if API returns error" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 400 - wsResponse.json returns Helper.loadJson("providers/oauth2/vk.error.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(400) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/vk.error.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(SpecifiedProfileError.format( @@ -133,10 +136,10 @@ class VKProviderSpec extends OAuth2ProviderSpec { "fail with ProfileRetrievalException if an unexpected error occurred" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 500 - wsResponse.json throws new RuntimeException("") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(500) + when(wsResponse.json).thenThrow(new RuntimeException("")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) failed[ProfileRetrievalException](provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { case e => e.getMessage must equalTo(UnspecifiedProfileError.format(provider.id)) @@ -147,24 +150,24 @@ class VKProviderSpec extends OAuth2ProviderSpec { val url = "https://custom.api.url?access_token=%s" val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - oAuthSettings.apiURL returns Some(url) - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/vk.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(url.format("my.access.token")) returns wsRequest + when(oAuthSettings.apiURL).thenReturn(Some(url)) + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/vk.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(url.format("my.access.token"))).thenReturn(wsRequest) await(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) - there was one(httpLayer).url(url.format("my.access.token")) + verify(httpLayer).url(url.format("my.access.token")) } "return the social profile with email" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/vk.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/vk.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -179,10 +182,10 @@ class VKProviderSpec extends OAuth2ProviderSpec { "return the social profile from response without photo" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/vk.success.without.photo.json").as[JsObject] - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/vk.success.without.photo.json").as[JsObject]) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -197,10 +200,10 @@ class VKProviderSpec extends OAuth2ProviderSpec { "return the social profile from deprecated API response" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/vk.success.deprecated.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/vk.success.deprecated.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile(oAuthInfo.as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( @@ -215,10 +218,10 @@ class VKProviderSpec extends OAuth2ProviderSpec { "return the social profile without email" in new WithApplication with Context { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsResponse.json returns Helper.loadJson("providers/oauth2/vk.success.json") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(API.format("my.access.token")) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsResponse.json).thenReturn(Helper.loadJson("providers/oauth2/vk.success.json")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(API.format("my.access.token"))).thenReturn(wsRequest) profile(provider.retrieveProfile((oAuthInfo.as[JsObject] - "email").as[OAuth2Info])) { p => p must be equalTo CommonSocialProfile( diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/SteamProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/SteamProviderSpec.scala index ff97f310..6127b19e 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/SteamProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/SteamProviderSpec.scala @@ -18,6 +18,7 @@ package io.github.honeycombcheesecake.play.silhouette.impl.providers.openid import io.github.honeycombcheesecake.play.silhouette.api.LoginInfo import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import play.api.test.WithApplication +import org.mockito.Mockito._ /** * Test case for the [[SteamProvider]] class. @@ -32,7 +33,7 @@ class SteamProviderSpec extends OpenIDProviderSpec { val s = provider.withSettings(overrideSettingsFunction) s.settings.providerURL must be equalTo "new-provider-url" - there was one(openIDService).withSettings(overrideSettingsFunction) + verify(openIDService).withSettings(overrideSettingsFunction) } } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/YahooProviderSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/YahooProviderSpec.scala index 8c5581ed..fb654ebb 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/YahooProviderSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/YahooProviderSpec.scala @@ -18,6 +18,7 @@ package io.github.honeycombcheesecake.play.silhouette.impl.providers.openid import io.github.honeycombcheesecake.play.silhouette.api.LoginInfo import io.github.honeycombcheesecake.play.silhouette.impl.providers._ import play.api.test.WithApplication +import org.mockito.Mockito._ /** * Test case for the [[YahooProvider]] class. @@ -32,7 +33,7 @@ class YahooProviderSpec extends OpenIDProviderSpec { val s = provider.withSettings(overrideSettingsFunction) s.settings.providerURL must be equalTo "new-provider-url" - there was one(openIDService).withSettings(overrideSettingsFunction) + verify(openIDService).withSettings(overrideSettingsFunction) } } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/service/PlayOpenIDServiceSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/service/PlayOpenIDServiceSpec.scala index d4c232d3..038916ed 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/service/PlayOpenIDServiceSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/openid/service/PlayOpenIDServiceSpec.scala @@ -2,12 +2,12 @@ package io.github.honeycombcheesecake.play.silhouette.impl.providers.openid.serv import io.github.honeycombcheesecake.play.silhouette.impl.providers.OpenIDSettings import io.github.honeycombcheesecake.play.silhouette.impl.providers.openid.services.PlayOpenIDService -import org.specs2.mock.Mockito import org.specs2.specification.Scope +import org.mockito.Mockito.mock import play.api.libs.openid.OpenIdClient import play.api.test.{ PlaySpecification, WithApplication } -class PlayOpenIDServiceSpec extends PlaySpecification with Mockito { +class PlayOpenIDServiceSpec extends PlaySpecification { "The `withSettings` method" should { "create a new instance with customized settings" in new WithApplication with Context { @@ -35,7 +35,7 @@ class PlayOpenIDServiceSpec extends PlaySpecification with Mockito { "image" -> "http://axschema.org/media/image/default"), realm = Some("http://localhost:9000")) - val service = new PlayOpenIDService(mock[OpenIdClient], openIDSettings) + val service = new PlayOpenIDService(mock(classOf[OpenIdClient]), openIDSettings) } } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandlerSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandlerSpec.scala index 81266206..0652cd99 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandlerSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/CsrfStateItemHandlerSpec.scala @@ -21,11 +21,13 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialStateI import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialStateItem.ItemStructure import io.github.honeycombcheesecake.play.silhouette.impl.providers.state.CsrfStateItemHandler._ import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.libs.json.Json import play.api.mvc.{ Cookie, Results } import play.api.test.{ FakeRequest, PlaySpecification } +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mockSmart import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -34,11 +36,11 @@ import scala.util.Success /** * Test case for the [[CsrfStateItemHandler]] class. */ -class CsrfStateItemHandlerSpec extends PlaySpecification with Mockito with JsonMatchers { +class CsrfStateItemHandlerSpec extends PlaySpecification with JsonMatchers { "The `item` method" should { "return the CSRF state item" in new Context { - idGenerator.generate returns Future.successful(csrfToken) + when(idGenerator.generate).thenReturn(Future.successful(csrfToken)) await(csrfStateItemHandler.item) must be equalTo csrfStateItem } @@ -50,7 +52,7 @@ class CsrfStateItemHandlerSpec extends PlaySpecification with Mockito with JsonM } "should return `None` if it can't handle the given item" in new Context { - val nonCsrfState = mock[SocialStateItem].smart + val nonCsrfState = mockSmart[SocialStateItem] csrfStateItemHandler.canHandle(nonCsrfState) must beNone } @@ -58,8 +60,8 @@ class CsrfStateItemHandlerSpec extends PlaySpecification with Mockito with JsonM "The `canHandle` method" should { "return false if the give item is for another handler" in new Context { - val nonCsrfItemStructure = mock[ItemStructure].smart - nonCsrfItemStructure.id returns "non-csrf-item" + val nonCsrfItemStructure = mockSmart[ItemStructure] + when(nonCsrfItemStructure.id).thenReturn("non-csrf-item") implicit val request = FakeRequest() csrfStateItemHandler.canHandle(nonCsrfItemStructure) must beFalse @@ -107,7 +109,7 @@ class CsrfStateItemHandlerSpec extends PlaySpecification with Mockito with JsonM /** * The ID generator implementation. */ - val idGenerator = mock[IDGenerator].smart + val idGenerator = mockSmart[IDGenerator] /** * The settings. @@ -120,9 +122,9 @@ class CsrfStateItemHandlerSpec extends PlaySpecification with Mockito with JsonM * The signer returns the same value as passed to the methods. This is enough for testing. */ val signer = { - val c = mock[Signer].smart - c.sign(any()) answers { p: Any => p.asInstanceOf[String] } - c.extract(any()) answers { p: Any => Success(p.asInstanceOf[String]) } + val c = mockSmart[Signer] + when(c.sign(any())).thenAnswer(_.getArgument(0).asInstanceOf[String]) + when(c.extract(any())).thenAnswer(p => Success(p.getArgument(0).asInstanceOf[String])) c } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/UserStateItemHandlerSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/UserStateItemHandlerSpec.scala index c3984bbe..e32a8879 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/UserStateItemHandlerSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/providers/state/UserStateItemHandlerSpec.scala @@ -19,17 +19,18 @@ import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialStateI import io.github.honeycombcheesecake.play.silhouette.impl.providers.SocialStateItem.ItemStructure import io.github.honeycombcheesecake.play.silhouette.impl.providers.state.UserStateItemHandler._ import org.specs2.matcher.JsonMatchers -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.libs.json.Json import play.api.test.{ FakeRequest, PlaySpecification } +import org.mockito.Mockito._ +import test.Helper.mockSmart import scala.concurrent.ExecutionContext.Implicits.global /** * Test case for the [[UserStateItemHandler]] class. */ -class UserStateItemHandlerSpec extends PlaySpecification with Mockito with JsonMatchers { +class UserStateItemHandlerSpec extends PlaySpecification with JsonMatchers { "The `item` method" should { "return the user state item" in new Context { @@ -43,7 +44,7 @@ class UserStateItemHandlerSpec extends PlaySpecification with Mockito with JsonM } "should return `None` if it can't handle the given item" in new Context { - val nonUserState = mock[SocialStateItem].smart + val nonUserState = mockSmart[SocialStateItem] userStateItemHandler.canHandle(nonUserState) must beNone } @@ -51,8 +52,8 @@ class UserStateItemHandlerSpec extends PlaySpecification with Mockito with JsonM "The `canHandle` method" should { "return false if the give item is for another handler" in new Context { - val nonUserItemStructure = mock[ItemStructure].smart - nonUserItemStructure.id returns "non-user-item" + val nonUserItemStructure = mockSmart[ItemStructure] + when(nonUserItemStructure.id).thenReturn("non-user-item") implicit val request = FakeRequest() userStateItemHandler.canHandle(nonUserItemStructure) must beFalse diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/services/GravatarServiceSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/services/GravatarServiceSpec.scala index ca5b6a67..11af505a 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/services/GravatarServiceSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/services/GravatarServiceSpec.scala @@ -17,9 +17,11 @@ package io.github.honeycombcheesecake.play.silhouette.impl.services import io.github.honeycombcheesecake.play.silhouette.api.util.{ MockHTTPLayer, MockWSRequest } import io.github.honeycombcheesecake.play.silhouette.impl.services.GravatarService._ -import org.specs2.mock.Mockito import org.specs2.specification.Scope import play.api.test.PlaySpecification +import org.mockito.Mockito._ +import org.mockito.ArgumentMatchers.any +import test.Helper.mock import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -27,7 +29,7 @@ import scala.concurrent.Future /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.services.GravatarService]] class. */ -class GravatarServiceSpec extends PlaySpecification with Mockito { +class GravatarServiceSpec extends PlaySpecification { "The `retrieveURL` method" should { "return None if email is empty" in new Context { @@ -38,9 +40,9 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 404 - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(any) returns wsRequest + when(wsResponse.status).thenReturn(404) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(any)).thenReturn(wsRequest) await(service.retrieveURL(email)) should beNone } @@ -49,9 +51,9 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 404 - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(any) returns wsRequest + when(wsResponse.status).thenReturn(404) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(any)).thenReturn(wsRequest) await(service.retrieveURL(email)) should beNone } @@ -60,9 +62,9 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status throws new RuntimeException("Timeout error") - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(any) returns wsRequest + when(wsResponse.status).thenThrow(new RuntimeException("Timeout error")) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(any)).thenReturn(wsRequest) await(service.retrieveURL(email)) should beNone } @@ -71,9 +73,9 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(any) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(any)).thenReturn(wsRequest) await(service.retrieveURL(email)) should beSome(SecureURL.format(hash, "?d=404")) } @@ -82,10 +84,10 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - settings.secure returns false - wsResponse.status returns 200 - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(any) returns wsRequest + when(settings.secure).thenReturn(false) + when(wsResponse.status).thenReturn(200) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(any)).thenReturn(wsRequest) await(service.retrieveURL(email)) should beSome(InsecureURL.format(hash, "?d=404")) } @@ -94,10 +96,10 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - settings.params returns Map("d" -> "http://example.com/images/avatar.jpg", "s" -> "400") - wsResponse.status returns 200 - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(any) returns wsRequest + when(settings.params).thenReturn(Map("d" -> "http://example.com/images/avatar.jpg", "s" -> "400")) + when(wsResponse.status).thenReturn(200) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(any)).thenReturn(wsRequest) await(service.retrieveURL(email)) should beSome( SecureURL.format(hash, "?d=http%3A%2F%2Fexample.com%2Fimages%2Favatar.jpg&s=400")) @@ -107,9 +109,9 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { val wsRequest = mock[MockWSRequest] val wsResponse = mock[MockWSRequest#Response] - wsResponse.status returns 200 - wsRequest.get() returns Future.successful(wsResponse) - httpLayer.url(any) returns wsRequest + when(wsResponse.status).thenReturn(200) + when(wsRequest.get()).thenReturn(Future.successful(wsResponse)) + when(httpLayer.url(any)).thenReturn(wsRequest) await(service.retrieveURL("123test@test.com")) should beSome( SecureURL.format("0d77aed6b4c5857473c9a04c2017f8b8", "?d=404")) @@ -126,7 +128,7 @@ class GravatarServiceSpec extends PlaySpecification with Mockito { */ val httpLayer = { val m = mock[MockHTTPLayer] - m.executionContext returns global + when(m.executionContext).thenReturn(global) m } diff --git a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/util/PlayCacheLayerSpec.scala b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/util/PlayCacheLayerSpec.scala index 56510f0f..a5c63671 100644 --- a/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/util/PlayCacheLayerSpec.scala +++ b/silhouette/test/io/github/honeycombcheesecake/play/silhouette/impl/util/PlayCacheLayerSpec.scala @@ -15,7 +15,7 @@ */ package io.github.honeycombcheesecake.play.silhouette.impl.util -import org.specs2.mock.Mockito +import org.mockito.Mockito._ import org.specs2.specification.Scope import play.api.cache.AsyncCacheApi import play.api.test.PlaySpecification @@ -27,15 +27,15 @@ import scala.concurrent.duration.Duration /** * Test case for the [[io.github.honeycombcheesecake.play.silhouette.impl.util.PlayCacheLayer]] class. */ -class PlayCacheLayerSpec extends PlaySpecification with Mockito { +class PlayCacheLayerSpec extends PlaySpecification { "The `find` method" should { "return value from cache" in new Context { - cacheAPI.get[ZonedDateTime]("id") returns Future.successful(Some(value)) + when(cacheAPI.get[ZonedDateTime]("id")).thenReturn(Future.successful(Some(value))) await(layer.find[ZonedDateTime]("id")) should beSome(value) - there was one(cacheAPI).get[ZonedDateTime]("id") + verify(cacheAPI).get[ZonedDateTime]("id") } } @@ -43,7 +43,7 @@ class PlayCacheLayerSpec extends PlaySpecification with Mockito { "save value in cache" in new Context { await(layer.save("id", value)) - there was one(cacheAPI).set("id", value, Duration.Inf) + verify(cacheAPI).set("id", value, Duration.Inf) } } @@ -51,7 +51,7 @@ class PlayCacheLayerSpec extends PlaySpecification with Mockito { "removes value from cache" in new Context { await(layer.remove("id")) must beEqualTo(()) - there was one(cacheAPI).remove("id") + verify(cacheAPI).remove("id") } } @@ -63,7 +63,7 @@ class PlayCacheLayerSpec extends PlaySpecification with Mockito { /** * The cache API. */ - lazy val cacheAPI = mock[AsyncCacheApi] + lazy val cacheAPI = mock(classOf[AsyncCacheApi]) /** * The layer to test.