Skip to content

Instantly share code, notes, and snippets.

@jamesthompson
Created March 24, 2015 16:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamesthompson/3026d8c7feb507982399 to your computer and use it in GitHub Desktop.
Save jamesthompson/3026d8c7feb507982399 to your computer and use it in GitHub Desktop.
Testing JSON encoding using Lenses and Arbitrary Generators
import argonaut._, Argonaut._
import org.scalacheck._, Prop._
import scalaz._, Scalaz._
object EncodingTestExample extends Properties("Encoding Json Test Example") {
case class Vehicle(
wheelsCount: Option[Int],
engineParts: List[String]
)
implicit def vehicleEncoder: EncodeJson[Vehicle] =
EncodeJson(v =>
("wheelsCount" :=? v.wheelsCount) ->?:
("engineParts" := v.engineParts.asJson) ->:
jEmptyObject
)
def genVehicle: Gen[Vehicle] = for {
wheelsCount <- Gen.option[Int](Gen.choose(0, 8))
engineParts <- Gen.listOf(Gen.alphaStr)
} yield Vehicle(wheelsCount, engineParts)
def wheelsCountPL: Json @?> Json = jObjectPL >=> jsonObjectPL("wheelsCount")
def wheelsCountNumberPL: Json @?> Double = wheelsCountPL >=> jNumberPL
def enginePartsPL: Json @?> Json = jObjectPL >=> jsonObjectPL("engineParts")
def enginePartsArrayPL: Json @?> List[Json] = enginePartsPL >=> jArrayPL
property("vehicleEncoder") = forAll(genVehicle) {
(v: Vehicle) =>
val json = v.asJson
("wheelsCount field is serialized if Some" |: {
val res = wheelsCountPL.get(json).isEmpty
val expected = v.wheelsCount.isEmpty
res === expected
}) &&
("wheelsCount is correctly encoded as an optional string" |: {
val res = wheelsCountNumberPL.get(json).map(_.toInt)
val expected = v.wheelsCount
res === expected
}) &&
("engineParts field is always serialized" |: {
val res = enginePartsPL.get(json).isEmpty
val expected = false
res === expected
}) &&
("engineParts is always encoded as a list of strings" |: {
val res = enginePartsArrayPL.get(json).flatMap(_.traverseU(jStringPL.get)).isEmpty
val expected = false
res === expected
}) &&
("engineParts is always encoded as the same list of strings" |: {
// using .get is bad, but we check that the list isn't empty in the previous property
val res = enginePartsArrayPL.get(json).flatMap(_.traverseU(jStringPL.get)).get
val expected = v.engineParts
res === expected
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment