ScalaPlay> 2.6如何在测试中伪造一个简单的服务器时访问POST请求

问题描述 投票:1回答:1

我正在尝试使用Play2.7设置虚假服务器,https://developer.lightbend.com/guides/play-rest-api/建议的环境只是从POST请求中回显json。虽然我能够使GET和POST请求返回硬连线值,但我无法直接访问返回或处理它的请求。注意:这对版本<2.6是可行的,但现在Action已经被弃用了,所以我想知道在Play> = 2.6中处理这个问题的正确方法

我已经阅读了以下how to mock external WS API calls in Scala Play frameworkHow to unit test servers in Play 2.6 now that Action singleton is deprecated,它们实际上正在做我几乎所有的尝试,但似乎我需要一些不同的东西来访问请求。在之前的Play版本中,我可以执行以下操作:

case POST(p"/route") => Action { request => Ok(request.body.asJson.getOrElse(JsObject.empty)) }

但是,因为我收到了“臭名昭着”的话,所以这种行为似乎不太可能。

object Action in package mvc is deprecated: Inject an ActionBuilder (e.g. DefaultActionBuilder) or extend BaseController/AbstractController/InjectedController

错误。

我的实际工作代码是

object FakeServer {

  def withServerForStep1[T](codeBlock: WSClient => T): T =
    Server.withRouterFromComponents() { cs =>
      {
        case POST(p"/route") =>
          cs.defaultActionBuilder {
            Results.Ok(Json.arr(Json.obj("full_name" -> "octocat/Hello-World")))
          }
      }
    } { implicit port =>
      WsTestClient.withClient(codeBlock)
    }
}

和单位规格是类似的

"The step 1" should {
    "Just call the fakeservice" in {
      setupContext()
      FakeServer.withServerForStep1 ( {
        ws =>
          val request = ws.url("/route")
          val data = Json.obj(
            "key1" -> "value1",
            "key2" -> "value2"
          )
          val response = request.post(data).futureValue

          response.status mustBe 200
          response.body mustBe Json.toJson(data)

      })
    }
  }

我想以这样的方式编写FakeServer,以便Spec成功检查返回的主体是否等于原始发送的json。目前它显然失败了

"[{"full_name":"octocat/Hello-World"}]" was not equal to {"key1":"value1","key2":"value2"}
scala unit-testing playframework
1个回答
1
投票

我最终找到了如何做到这一点,并且在Scala中经常发生的正确方法是......微不足道的。

“技巧”只是在request =>的身体中添加cs.defaultActionBuilder,如下一个示例

 object FakeServer {

  def withServerForStep1[T](codeBlock: WSClient => T): T =
    Server.withRouterFromComponents() { cs =>
      {
        case POST(p"/route") =>

          cs.defaultActionBuilder { request =>
            val bodyAsJson = request.body.asJson.getOrElse(JsObject.empty)
            Results.Ok(bodyAsJson)
          }
      }
    } { implicit port =>
      WsTestClient.withClient(codeBlock)
    }
}

然后测试只需要处理可能的额外包装引用和读取

 val response = request.post(data).futureValue

        response.status mustBe 200
        response.body mustBe Json.toJson(data).toString()
© www.soinside.com 2019 - 2024. All rights reserved.