I have the following algebra
// domain
case class User(id: String, name: String, age: Int)
// algebra
trait UserRepositoryAlgebra[F[_]] {
def createUser(user: User): F[Unit]
def getUser(userId: String): F[Option[User]]
}
I have a InMemoryInterpreter for development cycle. There would be more interpreters coming up in time. My intention is to attempt scalatest with property based tests and not bind with any specific interpreter. Basically, there needs to be laws/properties for UserRepository that every interpreter should satisfy.
I could come up with one as
trait UserRepositorySpec_1 extends AnyWordSpec with Matchers with ScalaCheckPropertyChecks {
"UserRepository" must {
"create and retrieve users" in {
//problem: this is tightly coupling with a specific interpreter. How to test RedisUserRepositoryInterpreter, for example, follwing DRY ?
val repo = new InMemoryUserRepository[IO]
val userGen: Gen[User] = for {
id <- Gen.alphaNumStr
name <- Gen.alphaNumStr
age <- Gen.posNum[Int]
} yield User(id, name, age)
forAll(userGen) { user =>
(for {
_ <- repo.createUser(user)
mayBeUser <- repo.getUser(user.id)
} yield mayBeUser).unsafeRunSync() must be(Option(user))
}
}
}
}
I have something like this in mind.
trait UserRepositorySpec[F[_]] extends AnyWordSpec with Matchers with ScalaCheckPropertyChecks {
import generators._
def repo: UserRepositoryAlgebra[F]
"UserRepository" must {
"create and find users" in {
forAll(userGen){ user => ???
}
}
}
}