如何测试含Json BodyParser的Play REST API?编译失败求助
解决Play Scala中使用
parse.json时测试缺少隐式Materializer的问题 我刚碰到过完全一样的坑!问题出在parse.json这个BodyParser依赖**隐式的akka.stream.Materializer**来处理流式JSON解析,而你的测试环境里没有自动提供这个隐式值——反观不带BodyParser的index()方法,它不需要处理流操作,所以测试能正常编译。
下面给你两种最实用的解决办法:
方法1:手动声明隐式Materializer
如果你的测试不需要完整启动Play应用,可以直接创建一个Materializer并标记为隐式:
import org.scalatestplus.play._ import play.api.mvc._ import play.api.test._ import play.api.test.Helpers._ import akka.stream.Materializer import play.api.libs.json.Json class HomeControllerSpec extends PlaySpec with Results { // 用Akka系统的默认实现创建隐式Materializer implicit val materializer: Materializer = Materializer.matFromSystem "HomeController" should { "return OK when handling JSON requests" in { // 创建控制器实例 val controller = new HomeController(stubControllerComponents()) // 构造带JSON请求体的测试请求 val jsonRequest = FakeRequest(POST, "/json") .withJsonBody(Json.obj("testKey" -> "testValue")) // 调用action并断言结果状态 val result = controller.json()(jsonRequest) status(result) mustBe OK } } }
方法2:利用Guice测试特质自动注入依赖
如果你的项目用Guice做依赖注入,推荐用GuiceOneAppPerTest特质——它会启动轻量Play应用实例,自动注入所有需要的隐式依赖(包括Materializer):
import org.scalatestplus.play.guice._ import play.api.mvc._ import play.api.test._ import play.api.test.Helpers._ import play.api.libs.json.Json class HomeControllerSpec extends PlaySpec with GuiceOneAppPerTest with Injecting { "HomeController" should { "return OK for JSON requests" in { // 直接注入控制器实例 val controller = inject[HomeController] val jsonRequest = FakeRequest(POST, "/json") .withJsonBody(Json.obj("testKey" -> "testValue")) val result = controller.json()(jsonRequest) status(result) mustBe OK } } }
额外说明
- 你也可以手动给
stubControllerComponents()传入Materializer:stubControllerComponents(materializer = yourMaterializer) - 为什么
index()测试没问题?因为普通的Action { ... }不需要解析请求体的流,所以不依赖Materializer;而Action(parse.json)需要流式处理JSON请求体,必须有Materializer才能正常工作。
内容的提问来源于stack exchange,提问作者Saskia
相关产品推荐
相关产品推荐

