【问题标题】:Invalid Json: No content to map due to end-of-input when using play body parser无效的 Json:使用播放正文解析器时,由于输入结束,没有要映射的内容
【发布时间】:2017-06-27 10:53:41
【问题描述】:

我正在尝试测试一个尝试解析请求中发送的 JSON 的控制器方法:

  def addRoomToProfileForTime = Action.async(parse.json[AddRoomToProfileForTimeRequest]) { request =>
    profileService.addRoomToProfileForTime(request.body.roomId, request.body.profileId, request.body.timeRange).value.map {
      case Xor.Right(_)  => Ok
      case Xor.Left(err) => BadRequest(Json.toJson(err))
    }
  }

这是代表请求的案例类:

final case class AddRoomToProfileForTimeRequest(
  roomId: Int,
  profileId: Int,
  timeRange: TimeRange
)

implicit val addRoomToProfileForTimeRequestFormat:Format[AddRoomToProfileForTimeRequest] = Json.format

此代码按预期工作,我提出这样的请求:

curl -H "Content-Type: application/json" -X POST -d '{"roomId":3,"profileId":1,"timeRange":{"id":1,"fromTime":"2000-01-01T01:01","toTime":"2000-01-01T02:01"}}' http://localhost:9000/api/profiles/addRoomToProfileForTime

但我正在尝试为此方法编写测试(请注意,我使用 macwire 进行依赖注入,因此无法使用 WithApplication:

"add a room to profile for time" in new TestContext {
  val roomId = 1
  val profileId = 1
  val from = "2000-01-01T01:01"
  val to = "2000-01-01T02:01"
  val requestJson = Json.obj(
    "roomId"    -> roomId,
    "profileId" -> profileId,
    "timeRange" -> Json.obj(
      "id"       -> 1,
      "fromTime" -> from,
      "toTime"   -> to
    )
  )

  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()

  val fakeReq = FakeRequest(Helpers.POST, "api/profiles/addRoomToProfileForTime")
    .withHeaders(CONTENT_TYPE -> "application/json")
    .withJsonBody(requestJson)
  val result = profileController.addRoomToProfileForTime()(fakeReq).run

  val content  = contentAsString(result)
  println(content)
  status(result) must equalTo(OK)
}

但是,此测试因 Play 的错误请求而失败:

<body>                                             
    <h1>Bad Request</h1>                                

    <p id="detail">
        For request 'POST api/profiles/addRoomToProfileForTime' [Invalid Json: No content to map due to end-of-input at [Source: akka.util.ByteIterator$ByteArrayIterator$$anon$1@37d14073; line: 1, column: 0]]
    </p>

</body>

如果我使用 request.body.asJson 解析 JSON,则该方法的行为符合预期。只有使用上面的正文解析器方法才会出现此错误。

【问题讨论】:

标签: scala playframework


【解决方案1】:

简短的回答是:在您的控制器测试中的FakeRequest 上使用withBody 方法而不是withJsonBody

我也遇到了这个问题,我尴尬地花了几个小时才弄明白。长答案是FakeRequestwithJsonBody 返回FakeRequest[AnyContentAsJson],并且由于您的控制器期待JsValue不是 AnyContentAsJson),当您调用apply()在您的操作中,它无法匹配此应用方法,这是您想要的方法:

def apply(request: Request[A]): Future[Result]

会点击这个 apply 方法:

def apply(rh: RequestHeader): Accumulator[ByteString, Result]

因此,由于您没有将任何字节传递给累加器,因此您会收到意外的 end-of-input 错误消息。

【讨论】:

【解决方案2】:

另一个原因可能是没有在 Postman 应用程序中设置 Content-Length。我错误地禁用了它,忘记启用它。 .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-11
    • 2019-04-13
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多