1

我正在使用 Play Framework 来简化 Scala 中的 JSON 解析。我的代码如下所示:

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()
}

现在,如果我提供正确的用户名和密码,我肯定会token在我的res对象内部得到一个。所以我在 Scala 中编写了一个测试用例,目前看起来像这样,其中我没有传递有效的用户名和密码:

class ApiCheckerTest extends FunSuite {
    test("ApiChecker.getAuthToken") {
        assert(ApiChecker.getAuthToken("" , "") == null)
    }
}

当我尝试运行它时,我得到了这个异常:

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)getAuthToken函数的最后一行。

如何测试我是否token在场res

4

1 回答 1

2

res("token")res.apply("token")

你有一个reswhich 是 type JsValue。并且JsValue有一个 apply 方法接受 aString并返回 another JsValue。现在这个apply方法的问题是它也可以抛出异常,这里看看方法

/**
   * Access a value of this array.
   *
   * @param fieldName Element index.
   */
  def apply(fieldName: String): JsValue = result match {
    case JsDefined(x) => x match {
      case arr: JsObject => arr.value.lift(fieldName) match {
        case Some(x) => x
        case None => throw new NoSuchElementException(String.valueOf(fieldName))
      }
      case _ =>
        throw new Exception(x + " is not a JsObject")
    }
    case x: JsUndefined =>
      throw new Exception(String.valueOf(x.error))
  }

但是您编写的函数只返回一个字符串,让异常冒泡。

def getAuthToken(userid: String, password: String): String

所以有两种前进的方式,要么你改变返回类型也表明你的函数可以出错

def getAuthToken(userid: String, password: String): Try[String] = {
    val body: JsValue = Json.obj("userid" -> userid , "password" -> password)

    val res = Json.parse(Http("https://<some url>")
        .postData(body.toString()).asString.body)

    Try(res("token").toString())
}

或者,保持相同的设置并仅在 try catch 块内调用您的方法。

我会说使用Try[String]返回类型,或者如果您只关心令牌是否存在,请使用Option[String]返回类型。这是一个示例

def getAuthToken(userid: String, password: String): Option[String] = {
    val body: JsValue = Json.obj("userid" -> userid , "password" -> password)

    val res = Json.parse(Http("https://<some url>")
        .postData(body.toString()).asString.body)

    Try(res("token").toString()).toOption
}

这使您的代码更安全且更易于测试,现在您只需检查结果是否NoneSome(token).

于 2019-08-03T01:38:25.320 回答