我想为控制器编写一个简单的测试,它接受 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
}
}
有关
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
看来你需要在控制器中注入一个物化器:
class Controller @Inject() (implicit val mat: Materializer) { ??? }