Play Framework& Scala:FakeRequest的问题&单元测试中的JSON POST

时间:2013-10-30 23:52:34

标签: json unit-testing scala playframework

我花了太多时间尝试调试以下问题,但我不确定问题出在哪里。

问题:将400 Bad Request, Invalid Json作为响应,但有以下异常:

com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
 at [Source: [B@6ee503c9; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) ~[jackson-databind.jar:2.2.2]
    at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:2931) ~[jackson-databind.jar:2.2.2]
    at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2846) ~[jackson-databind.jar:2.2.2]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1569) ~[jackson-databind.jar:2.2.2]
    at play.api.libs.json.JacksonJson$.parseJsValue(JsValue.scala:480) ~[play-json_2.10.jar:2.2.0]
    at play.api.libs.json.Json$.parse(Json.scala:27) ~[play-json_2.10.jar:2.2.0]

在我的控制器中测试的方法:

  def createArticle(id: String) =
      Action.async(parse.json) { implicit request =>
        (request.body \ "content").asOpt[String].map {
            ............
            ............
        }.getOrElse(BadRequest("Invalid request body"))
      }

相应的单元测试:

  "create article" in {
    running(FakeApplication()) {
      val postJson = Json.obj("content" -> "article content")

      val result = resource.createArticle(ARTICE_ID)(FakeRequest(POST, controllers.routes.ArticleResource.create(ARTICLE_ID).url).withJsonBody(postJson).withHeaders(CONTENT_TYPE -> "application/json").run

      status(result) must equalTo OK
    }
  }

我阅读了here的讨论,但没有任何建议有帮助。

3 个答案:

答案 0 :(得分:0)

我有类似的问题,但到目前为止还没有解决它们(优雅地,无论如何......)。由于我的环境是java而不是scala,我可以直截了当。我认为当你发送邮件时它可能是异步完成的(Action.async在你的创建文章方法中),所以你可能需要等待测试代码结果才能看到它是否正常。

答案 1 :(得分:0)

我遇到了类似的问题,解决方案是here。在我的情况下,这是因为我使用response.asJson()两次,并且如@jroper

所述
  

考虑到HTTP响应的主体是流,而不是   你想要在内存中缓冲的东西,然后它会   感觉两次访问身体(无论你是什么格式   不支持访问正文。

答案 2 :(得分:0)

尝试在方法定义中实例化您的请求。

这就是它对我有用的方法(例如使用带有JSON主体的POST和结果为JSON的示例):

"process" should {
    "should be valid" in {
 val request = FakeRequest(POST, "/").withJsonBody(Json.parse("""      {  
     "id":1,
     "name":"prod 1",
     "price":55.55
  }"""))

  val result: Future[Result] = controller.process.apply(request)      
  val json = contentAsJson(result)            

  status(result) must be(CREATED)
  (json \ "id").as[Int] mustBe 1

// .. more assertions and rest of code ...

此处代码处理JsValue并查询其节点以检查返回的值是否与所需的模拟数据输出匹配