如何使用 Json BodyParser 测试 Play REST API?

问题描述 投票:0回答:2

我想为控制器编写一个简单的测试,它接受 json 主体。但是,一旦我将

parse.json
BodyParser 添加到操作中,我的测试就无法再编译了。 安装程序基本上是简单的 play-scala-seed 项目。

错误:

[error] ... could not find implicit value for parameter mat: akka.stream.Materializer
[error]       status(home) mustBe OK
[error]             ^

HomeController

def index() = Action { implicit request =>
  Ok
}

def json() = Action(parse.json) { implicit request =>
  Ok
}

HomeControllerSpec

class HomeControllerSpec extends PlaySpec with GuiceOneAppPerTest with Injecting {
  "HomeController POST" should {
    "answer Ok" in {
      val controller = new HomeController(stubControllerComponents())
      val home = controller.json().apply(FakeRequest(POST, "/"))
      status(home) mustBe OK
    }
  }
scala playframework scalatest playframework-2.6
2个回答
3
投票

有关

stubControllerComponents
FakeRequest
调用的代码似乎存在两个问题。

Helpers.stubControllerComponents
默认构造
ControllerComponents
NoMaterializer
,使用时只会抛出异常,所以我们需要提供一个实际的物化器,如下所示:

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

       Helpers.stubControllerComponents(
         playBodyParsers = Helpers.stubPlayBodyParsers(materializer)
       ) 

第二个问题是

FakeRequest
,我们需要提供如下的主体(否则我们会得到
4xx
错误):

FakeRequest(POST, "/json").withBody(Json.obj("name" -> "Jon Doe"))

考虑到上述情况,我们可以编写完整的测试如下:

class HomeControllerSpec extends PlaySpec with GuiceOneAppPerTest {
  "HomeController POST" should {
    "answer Ok" in {
       implicit val materializer = ActorMaterializer()(ActorSystem())

       val controllerComponents = 
         Helpers.stubControllerComponents(
           playBodyParsers = Helpers.stubPlayBodyParsers(materializer)
         ) 

       val controller = new HomeController(controllerComponents)

       val fakeRequest = 
         FakeRequest(POST, "/json").withBody(Json.obj("name" -> "Jon Doe"))

       val home = call(controller.json(), fakeRequest)

       status(home) mustBe OK
    }
  }
}

2023 年更新

apply 方法

ActorMaterializer()
已弃用,现在构建物化器实例的推荐方法如下。

implicit val materialzer = SystemMaterializer(ActorSystem()).materializer

3
投票

看来你需要在控制器中注入一个物化器:

class Controller @Inject() (implicit val mat: Materializer) { ??? }

© www.soinside.com 2019 - 2024. All rights reserved.