文章目錄
  1. 1. 版本 !!!!
  2. 2. Override configuration
  3. 3. Unit testing
  4. 4. Controller testing
  5. 5. JSON Read & Write
  6. 6. Reference

個人覺得Play 的文件比較亂。在這裡先記下簡約play testing 的用法

版本 !!!!

十分重要, 因為各個版本的api 可以差別很大…

  • Play version: 2.4.6
  • Scala version: 2.1.0

Override configuration

因為我只預設用一個database。。。

1
2
3
4
5
6
7
trait 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import play.api.test.PlaySpecification
import DAO.UserDAO

import play.api._
import play.api.test._
import play.api.test.Helpers._

class UserDAOSpec extends PlaySpecification with DAOTrait {


val testUserEmail = "test@hotmail.com"
val testUserPassword = "1234"

step(Play.start(fakeApp))

"The User DAO" should {
"register" in {
val id = UserDAO.register(testUserEmail, testUserPassword);
(id.get > 0) must beTrue
}
"isExist" in {
UserDAO.isExist(testUserEmail) must beTrue
UserDAO.isExist("this is not a email") must beFalse
}
"validate" in {
UserDAO.validate(testUserEmail, testUserPassword) must beTrue
UserDAO.validate(testUserEmail, "9999") must beFalse
}
"delete" in {
UserDAO.delete(testUserEmail) must beTrue
}

}

step(Play.stop(fakeApp))
}

Controller testing

測試json post request
另外寫法val request = FakeRequest(POST, "/").withJsonBody(Json.parse("""{ "field": "value" }"""))
body 請放JsValue, 不要放String
contentTypecontentAsJson 在play.api.test.Helpers
如果你只需測試routing,你不需要用step 啟動applicaton, 整個controller的method不會執行
return 的可以是Future[Result]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import controllers.RecipeController
import play.api.Logger
import play.api.libs.json._

import play.api._
import play.api.test._
import play.api.test.Helpers._

class RecipeControllerSpec extends PlaySpecification with DAOTrait{

step(Play.start(fakeApp))

"Example Page#index" should {
"should be valid" in {

var jsonHeader = Seq(("Content-Type", "application/json; charset=utf-8"))
val jsValue = Json.obj("ingredients" -> Json.arr("牛奶", "奶"))
val controller = new RecipeController()
val fakeRequest = FakeRequest(Helpers.POST, "api/user/searchIngredient", new FakeHeaders(jsonHeader), jsValue);

val result = controller.searchIngredient().apply(fakeRequest)
val ct = contentType(result)
ct must equalTo(Some("application/json"))
// Logger.debug("really content type" + contentAsString(result))
val jsContent : JsValue = contentAsJson(result)
jsContent.as[JsArray].value.size must equalTo(6)
}
}

step(Play.stop(fakeApp))
}

JSON Read & Write

play framework 設計JSON要read 進一個model & 或由一個model write 成JSON
如果json的數目跟model attribute不同比較麻煩

把一個value 變做object, 利用scala 的map pattern 提取value

1
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) 變成UserRecipeRating

1
2
3
4
5
val 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
5
val writeJson = (obj: UserRecipeRating) => (obj.recipeId , obj.rating)
implicit val write : Writes[Write] = (
(JsPath \ "recipeId").write[Int] and
(JsPath \ "rating").write[Int]
)(writeJson)

Reference

JSON Basic
Helper Method

文章評論

文章目錄
  1. 1. 版本 !!!!
  2. 2. Override configuration
  3. 3. Unit testing
  4. 4. Controller testing
  5. 5. JSON Read & Write
  6. 6. Reference