我正在尝试使用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 framework和How 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中经常发生的正确方法是......微不足道的。
“技巧”只是在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()