iTa*_*shi 3 scala playframework playframework-2.4
我正在开发一个 play-2.4 项目,并编写了一个控制器,如下所示:
package controllers
import play.api._
import play.api.mvc._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
class Application extends Controller {
def index = Action.async { implicit request =>
Future { Ok(request.body.asJson.get) }
}
}
Run Code Online (Sandbox Code Playgroud)
之POST / controllers.Application.index内
conf/routes。
我通过执行检查这工作正常curl --request POST --header "Content-type: application/json" --data '{"foo":"bar"}' http://localhost:9000/。
现在我为这个控制器编写了一个规范:
package controllers
import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._
import play.api.test._
import play.api.test.Helpers._
@RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification {
"Application" should {
val controller = new Application
val fakeJson = """{ "foo":"bar" }"""
val fakeRequest = FakeRequest()
.withHeaders("Content-type" -> "application/json")
.withBody(fakeJson)
val index = controller.index()(fakeRequest).run
status(index) must equalTo(OK)
}
}
Run Code Online (Sandbox Code Playgroud)
但这导致了运行时错误:
[error] None.get (Application.scala:11)
[error] controllers.Application$$anonfun$index$1$$anonfun$apply$1.apply(Application.scala:11)
[error] controllers.Application$$anonfun$index$1$$anonfun$apply$1.apply(Application.scala:11)
Run Code Online (Sandbox Code Playgroud)
我插入println(request.body)控制器,发现请求正文是AnyContentAsEmpty,意思fakeJson是从 中删除fakeRequest。
如何正确地将 JSON 附加到 FakeRequest?
*注意:虽然我可以这样写FakeRequest(POST, '/', FakeHeaders(), fakeJson),但我认为这不好,因为控制器规范不应该处理 HTTP 方法或路由。
我将不胜感激任何帮助。
如果客户端使用非JSON的请求向您的操作发出 HTTP POST ,request.body.asJson.get将引发异常。
body.asJson有返回类型,如果请求不是 JSON,Option[JsValue]则返回 a 。NonegetaNone会抛出 a java.util.NoSuchElementException。500 Internal Server Error.您应该替换为使用 JSON主体解析器的def index = Action.async ...操作:
import play.api.mvc.BodyParsers.parse
def index = Action.async(parse.json) ...
Run Code Online (Sandbox Code Playgroud)
这实现了一些目标:
400 Bad Request如果 POST 不是 JSON,Play 将生成一个。这比500 Internal Server Error你造成的更合适None.get。request.body代替.JsValue AnyContent所以你可以request.body.asJson.get简单地替换为request.body. 一般来说,您应该避免调用,Option.get因为它不安全,并且通常有更好的方法来实现您想要的(在这种情况下,使用适当的正文解析器恰好是更好的方法)。现在这个测试不再编译,而不是抛出由以下原因引起的异常None.get:
val fakeJson = """{ "foo":"bar" }"""
val fakeRequest = FakeRequest()
.withHeaders("Content-type" -> "application/json")
.withBody(fakeJson)
val index = controller.index()(fakeRequest)
status(index) must equalTo(OK)
Run Code Online (Sandbox Code Playgroud)
强制您将其替换为答案中的版本:
val fakeJson = play.api.libs.json.Json.parse("""{ "foo":"bar" }""")
val fakeRequest = FakeRequest().withBody(fakeJson)
val index = controller.index()(fakeRequest)
status(index) must equalTo(OK)
Run Code Online (Sandbox Code Playgroud)
我最后的建议是你用来Json.obj清理你的测试:
val fakeJson = Json.obj("foo" -> "bar")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2511 次 |
| 最近记录: |