My controller has an Action
signInUser
which is called when a user send a login request. In the Action, I retrieve username and password from json
body of the request and call CredentialProvider
def signInUser = silhouette.UserAwareAction.async { implicit request => {
val body: AnyContent = request.body
val jsonBody: Option[JsValue] = body.asJson
jsonBody match {
case Some(json) => {
val readableString: String = Json.prettyPrint(json)
val userSigninOption: Option[UserSigninAPI] = json.asOpt[UserSigninAPI] //check if json conforms with UserProfile structure
userSigninOption match {
case Some(signinInfo) => { //format of JSON is correct
val credentials: Credentials = Credentials(signinInfo.signinInfo.email, signinInfo.signinInfo.password) //TODOM need to check that password is not empty
val authInfoRepository = new DelegableAuthInfoRepository(userRepo.passwordRepo)
val passwordHasherRegistory = new PasswordHasherRegistry(userRepo.passwordHasher)
val credentialsProvider = new CredentialsProvider(authInfoRepository, passwordHasherRegistory)
val loginInfoFuture: Future[LoginInfo] = credentialsProvider.authenticate(credentials)
loginInfoFuture.flatMap(loginInfo => {...}
.recover { case x => {
println("Future failed in signIn User. In recover. Returning Internal Server Error" + x)
x match {
case e:InvalidPasswordException =>{
Unauthorized(Json.toJson(JsonResultError("Incorrect username or password")))
}
case _ => {
InternalServerError(Json.toJson(JsonResultError("Internal Server Error. Reason "+x)))
}
}
}
...
I want to unit test the code. My unit test is crashing because the loginInfoFuture
gets NullPointerException
.
Some snippets from my unit test are
class TestEnv {
val mockAuthInfoRepository = mock(classOf[DelegableAuthInfoRepository])
val mockPasswordHasherRegistory = mock(classOf[PasswordHasherRegistry])
val mockCredentialsProvider = mock(classOf[CredentialsProvider])
....
implicit val fakeEnv = FakeEnvironment[JWTEnv](Seq(loginInfo -> user))
val defaultParser = new mvc.BodyParsers.Default()
val securedAction = new DefaultSecuredAction(new DefaultSecuredRequestHandler(new DefaultSecuredErrorHandler(stubMessagesApi())), defaultParser)
val unsecuredAction = new DefaultUnsecuredAction(new DefaultUnsecuredRequestHandler(new DefaultUnsecuredErrorHandler(stubMessagesApi())), defaultParser)
val userAware = new DefaultUserAwareAction(new DefaultUserAwareRequestHandler(), defaultParser)
val fakeSilhouette = new SilhouetteProvider[JWTEnv](fakeEnv, securedAction, unsecuredAction, userAware)
}
"signInUser" should {
"sign in user with correct details" in {
val signInRequestJson = Json.parse(
"""
|{
|"signin-info": {
|"email":"",
|"password":"aA1!1111"
|}
|}
""".stripMargin
)
val request = FakeRequest("POST","ws/users/signin").withJsonBody(signInRequestJson)
println(s"will send request ${request} ")
val testEnv = new TestEnv(components.configuration)
// println(s"mocked identity service of silhouette is ${testEnv.fakeSilhouette.env.identityService}")
when(testEnv.mockCredentialsProvider.authenticate(ArgumentMatchers.any[Credentials])).thenReturn(
Future{
println(s"mocked credentials provider will return ${testEnv.loginInfo}")
testEnv.loginInfo}
)
val resultFuture = testEnv.controller.signInUser(request)
val result = contentAsJson(resultFuture)
println(s"received result ${result}")
1 mustBe 1
}
}
The stack trace is
java.lang.NullPointerException
at com.mohiva.play.silhouette.persistence.repositories.DelegableAuthInfoRepository.$anonfun$find$1(DelegableAuthInfoRepository.scala:51)
at com.mohiva.play.silhouette.persistence.repositories.DelegableAuthInfoRepository.$anonfun$find$1$adapted(DelegableAuthInfoRepository.scala:51)