如何测试使用自定义bodyparser的play框架控制器?

时间:2016-12-09 16:53:05

标签: json playframework playframework-2.5

我正在尝试测试使用自定义bodyparser和JSON验证器的play framework 2.5.10控制器:

class MessagingController {
  def validateJson[A : Reads] = parse.json.validate(
    _.validate[A].asEither.left.map(e => BadRequest(JsError.toJson(e)))
  )
  def createMessageThread() = Action(validateJson[InboundMessageThread]) { request => 
    Ok("OK") }
  }

当我对此运行一个简单的测试用例时,我收到一个错误:

For request 'POST /api/v1/messageThreads' [Invalid Json: No content to map due to 
end-of-input at [Source: akka.util.ByteIterator$ByteArrayIterator$$anon$1@5693d1d2; line: 1, column: 0]]

测试是:

  val fakeRequest = FakeRequest()
      .withHeaders(HeaderNames.CONTENT_TYPE -> "application/json")
      .withBody(Json.parse(
        s"""
           |{
           |  "participants": [
           |   {"id": $currentUserId, "isAdmin": false}
           |  ],
           |  "isGroupThread": false
           |}
    """.stripMargin))

  val result =  messagingController.createMessageThread()(fakeRequest).run()
  status(result) mustBe OK

如果我将控制器的操作更改为Action,然后验证控制器主体中的JSON,它就可以工作。我不想这样做,因为我的许多REST控制器需要解析JSON并使用validateJson[T]减少样板。如果我使用curl提交相同的有效负载,代码也可以工作。

如何测试此控制器?

3 个答案:

答案 0 :(得分:1)

以下类型的请求有效:

val request = FakeRequest()
   .withHeaders(CONTENT_TYPE -> "application/json")
   .withBody(Json.fromJson[Place](body).get)

答案 1 :(得分:0)

试试这个,希望这会有所帮助

 val postRequest = FakeRequest(POST, "/route/to/hit").withJsonBody(Json.obj(
    "participants" -> Json.arr(Json.obj("id" -> "currentUserId", "isAdmin" -> false)),
    "isGroupThread" -> false
  ))

  val result =  await(messagingController.createMessageThread()(postRequest))

  status(result) must be equalTo (FORBIDDEN)

答案 2 :(得分:0)

我建议不要使用JSON bodyparser调用Action,而是建议使用AnyContent正文解析器调用ActionBuilder,然后从正文中调用Json.validate - 从那里,你得到堆栈跟踪并查看失败的原因:

class MessagingController {      
  def createMessageThread() = Action { request => 
    request.json.validate[MessageThread] {
      case JsError(e) =>           
         logger.error(s"Failure parsing because $e")
         BadRequest(JsError.toJson(e))
      case JsSuccess(e) =>      
         Ok("OK")
    }
  }
}