Play Testing and Json
更新日期:
個人覺得Play 的文件比較亂。在這裡先記下簡約play testing 的用法
版本 !!!!
十分重要, 因為各個版本的api 可以差別很大…
- Play version: 2.4.6
- Scala version: 2.1.0
Override configuration
因為我只預設用一個database。。。1
2
3
4
5
6
7trait DAOTrait {
implicit val fakeApp = new FakeApplication(
additionalConfiguration = Map("db.default.username" -> "YOURUSERNAME",
"db.default.url" -> "jdbc:mysql://URDATABASE",
"db.default.password" -> "YOURPASSWORD")
)
}
Unit testing
因為anorm database 要有execution context 所以要先用step 啟動application
1 | import play.api.test.PlaySpecification |
Controller testing
測試json post request
另外寫法val request = FakeRequest(POST, "/").withJsonBody(Json.parse("""{ "field": "value" }"""))
body 請放JsValue, 不要放StringcontentType
和 contentAsJson
在play.api.test.Helpers
如果你只需測試routing,你不需要用step 啟動applicaton, 整個controller的method不會執行
return 的可以是Future[Result]
1 | import controllers.RecipeController |
JSON Read & Write
play framework 設計JSON要read 進一個model & 或由一個model write 成JSON
如果json的數目跟model attribute不同比較麻煩
把一個value 變做object, 利用scala 的map pattern 提取value1
implicit val ingRead: Reads[IngIdWrap] = (JsPath \ "ingId").read[Int].map(IngIdWrap.apply);
Read的model attribute 比JSON value 多
UserRecipeRating 是(Int, Int, Int)
read的read combinator 會產生(Int, Int)
寫一個function 接收(Int, Int)
變成UserRecipeRating1
2
3
4
5val applyJson = (recipeId: Int, rating: Int) => UserRecipeRating(0, recipeId, rating);
implicit val read : Reads[UserRecipeRating] = (
(JsPath \ "recipeId").read[Int] and
(JsPath \ "rating").read[Int]
)(applyJson)
Write的model attribute 比JSON value 多
反過來,把一個UserRecipeRating 寫兩個Int, write combinator 需要(Int, Int)
可以寫一個function 接收一個UserRecipeRating 變作(Int, Int)
1
2
3
4
5val writeJson = (obj: UserRecipeRating) => (obj.recipeId , obj.rating)
implicit val write : Writes[Write] = (
(JsPath \ "recipeId").write[Int] and
(JsPath \ "rating").write[Int]
)(writeJson)