"GoogleOAuth2" should {
import play.api.libs.ws.Response
object TestSettings extends GoogleOAuth2Settings {
override lazy val clientId = testConfig("oauth2.google.cliend_id")
override lazy val clientSecret = testConfig("oauth2.google.cliend_secret")
override lazy val signInUrl = testConfig("oauth2.google.signInUrl")
override lazy val accessTokenUrl = testConfig("oauth2.google.accessTokenUrl")
override lazy val userInfoUrl = testConfig("oauth2.google.userInfoUrl")
override lazy val redirectUri = testConfig("oauth2.google.redirect_uri")
}
class MockedGoogleOauth2 extends GoogleOAuth2(TestSettings) {
override def url = testUrl _
lazy val requestHolder: WS.WSRequestHolder = mock[WS.WSRequestHolder]
def testUrl(s: String): WS.WSRequestHolder = {
requestHolder.url returns s
requestHolder
}
}
"requestAccessTokens" in {
import concurrent._
import ExecutionContext.Implicits.global
import concurrent.duration._
import play.api.http.{ Writeable, ContentTypeOf }
import org.mockito.Matchers.{ eq => mEq }
import org.mockito.Matchers
val underTest = new MockedGoogleOauth2()
val mockWs = underTest.requestHolder
val fakeResponse = mock[Response]
val expected = Map("client_id" -> Seq("client_id"), "client_secret" -> Seq("client_secret"), "code" -> Seq("code"), "redirect_uri" -> Seq("http://redirect"), "grant_type" -> Seq("authorization_code"))
type Params = Map[String, Seq[String]]
mockWs.post[Params](mEq(expected))(Matchers.any[Writeable[Params]], Matchers.any[ContentTypeOf[Params]]) returns Future.successful(fakeResponse)
//when
val willBeResponse = underTest.requestAccessTockenWS("code")
there was one(mockWs).post(mEq(expected))(any, any)
Await.result(willBeResponse, 5 milli) must beEqualTo(fakeResponse)
}
}
Spécifiquement pour la méthode, je pense que je suis allé trop loin, mais pour ce qui suit des tests me semblent nécessaires et le mécanisme que je vais utiliser pour tester sera le même.
De plus j'ai l'impression que la seconde version sera plus facile à mocker pour l'utilisateur de ce petit bout de code (moi probablement) et la technique sera sans doute la même : créer un val ou un def qui servira de provider et l'overrider pour les tests.
lazy val requestUserInfoUrl = WS.url(settings.userInfoUrl)
def requestAccessToken(code: String)(implicit executionContext: ExecutionContext): Future[String] = {
import scala.concurrent._
val willBeResponse = requestAccessTockenWS(code)
val actual: Future[Option[String]] = willBeResponse.map(response => (response.json \ "access_token").asOpt[String])
actual.flatMap(optS => optS.map(Future.successful(_)).getOrElse(Future.failed(new IllegalArgumentException("OAuth crendential error"))))
}
def authenticate[T](code: String)(implicit reads: Reads[T], executionContext: ExecutionContext) = requestAccessToken(code).flatMap(x => requestUserInfo(x))
def requestUserInfo[T](accessToken: String)(implicit reads: Reads[T], executionContext: ExecutionContext): Future[T] = {
val requestUrl = requestUserInfoUrl.withQueryString("access_token" -> accessToken)
user(requestUrl.get().map(_.body))
}
Avis et suggestions sont les bienvenus :)
Merci
Jean