ScalaPlay > 2.6 如何在测试中伪造普通服务器时访问 POST 请求

ScalaPlay > 2.6 how to access POST requests while faking a trivial server in tests

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

中哪种是处理此问题的正确方法

我已阅读以下内容 how to mock external WS API calls in Scala Play framework and ,它们实际上几乎完成了我想做的所有事情,但似乎我需要一些不同的东西来访问请求。在以前的 Play 版本中,我可以执行以下操作:

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

但似乎无法以这种方式调用操作,因为我收到了 'infamous'

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,使规范能够成功检查 returned 正文是否等于原始发送 json。目前它显然失败了

"[{"full_name":"octocat/Hello-World"}]" was not equal to {"key1":"value1","key2":"value2"}

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

"trick" 只是在 cs.defaultActionBuilder 的正文中添加 request =>,如下例所示

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