I'm using Play Framework for ease in JSON parsing in Scala. My code looks like:
def getAuthToken(userid: String, password: String): String = {
val body: JsValue = Json.obj("userid" -> userid , "password" -> password)
val res = Json.parse(Http("https://<some url>")
.postData(body.toString()).asString.body)
res("token").toString()
}
Now if I provide proper userid and password, I'm sure to get a token inside my res object. So I'm writing a test case in Scala which currently looks like this, where I don't pass a valid username and password:
class ApiCheckerTest extends FunSuite {
test("ApiChecker.getAuthToken") {
assert(ApiChecker.getAuthToken("" , "") == null)
}
}
When I try to run this, I get this exception raised:
token
java.util.NoSuchElementException: token
at play.api.libs.json.JsLookup$.apply$extension1(JsLookup.scala:68)
at ApiChecker$.getAuthToken(ApiChecker.scala:15)
at ApiCheckerTest$$anonfun$1.apply(ApiCheckerTest.scala:5)
at ApiCheckerTest$$anonfun$1.apply(ApiCheckerTest.scala:5)
at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
at org.scalatest.Transformer.apply(Transformer.scala:22)
at org.scalatest.Transformer.apply(Transformer.scala:20)
at org.scalatest.FunSuiteLike$$anon$1.apply(FunSuiteLike.scala:186)
at org.scalatest.TestSuite$class.withFixture(TestSuite.scala:196)
at org.scalatest.FunSuite.withFixture(FunSuite.scala:1560)
at org.scalatest.FunSuiteLike$class.invokeWithFixture$1(FunSuiteLike.scala:183)
...
ApiChecker$.getAuthToken(ApiChecker.scala:15) is the last line of the getAuthToken function.
How do I test whether I have token present in res or not?
res("token")is same asres.apply("token")You have a
reswhich is of typeJsValue. AndJsValuehas an apply method that takes in aStringand returns with anotherJsValue. Now the problem with this apply method is that it can also throw an exception, here have a look at the methodBut the function you wrote, only returns with a String and let's the exception bubble out.
So there are two ways of going forward, either you change the return type to also indicate that your function can error out
Or, keep the same setup and invoke your method only inside a try catch block.
I would say go with the
Try[String]return type or if you are only concerned with the token being present or not, use theOption[String]return type. Here's a sampleThis makes your code safer and easier to test, now you can just check that the result is
Noneinstead ofSome(token).