Skip to content

Instantly share code, notes, and snippets.

View supermanue's full-sized avatar

Manuel Rodríguez Pascual supermanue

View GitHub Profile
@supermanue
supermanue / fixtureTesting.scala
Created March 26, 2022 17:33
Fixture testing
object FixturesTest extends DefaultRunnableSpec with DomainFixtures {
def spec: ZSpec[TestEnvironment, Failure] =
suite("Fixtures test")(
testM("positiveIntGen generates positive ints") {
check(positiveIntGen) { positiveInt =>
assert(positiveInt > 0)(isTrue)
}
},
testM("nonemptyStringGen generates nonempty strings") {
object UserTest extends DefaultRunnableSpec with DomainFixtures {
def spec: ZSpec[TestEnvironment, Failure] =
suite("UserTest")(
testM("creating a user with valid input should succeed") {
check(positiveIntGen, nonemptyStringGen) { (positiveInt, nonemptyString) =>
val user = User.build(positiveInt, nonemptyString)
assert(user)(isRight)
}
},
testM("creating a user with id=0 should fail") {
@supermanue
supermanue / userService.scala
Created March 26, 2022 18:25
UserService class
object UserService {
def getUser(id: Int): ZIO[UserPersistence, AppError, User] = RIO.accessM(_.get.get(id))
def createUser(id: Int, name: String): ZIO[UserPersistence, AppError, User] =
for {
user <- ZIO.fromEither(User.build(id, name))
stored <- RIO.accessM[UserPersistence](_.get.create(user))
} yield stored
def deleteUser(id: Int): RIO[UserPersistence, Boolean] = RIO.accessM(_.get.delete(id))
}
@supermanue
supermanue / testDB.scala
Created March 26, 2022 18:30
testing DB
case class TestDB(users: Ref[Vector[User]]) extends StoragePort {
def get(id: Int): IO[AppError, User] =
users.get.flatMap(users => IO.require(UserNotFound(id))(Task.succeed(users.find(_.id.value == id))))
def create(user: User): IO[AppError, User] =
users.update(_ :+ user).map(_ => user)
def delete(id: Int): Task[Boolean] =
users.modify(users => true -> users.filterNot(_.id.value == id))
}
object TestDB {
object UserServiceTest extends DefaultRunnableSpec with DomainFixtures {
def spec: ZSpec[TestEnvironment, Failure] =
suite("UserService unit test")(
testM("get a non existing user should fail") {
assertM(getUser(100).run)(fails(anything))
},
testM("create a user then get it should return the same user ") {
checkM(userGen) { user =>
@supermanue
supermanue / sbt_extract.sbt
Last active April 4, 2022 06:43
SBT extract
val DoobieVersion = "0.12.1"
libraryDependencies ++= Seq(
"org.tpolecat" %% "doobie-core" % DoobieVersion,
"org.tpolecat" %% "doobie-h2" % DoobieVersion,
//needed for functional stuff
"dev.zio" %% "zio-interop-cats" % "2.0.0.0-RC12"
)
@supermanue
supermanue / UserAdapter
Created April 5, 2022 06:12
User in apdater layer
import zio.experiment.domain.model.AppError
import zio.experiment.domain.model.User.{ User => UserDomain }
case class User(id: Int, name: String)
object User {
implicit class UserConversions(user: User) {
def toDomainUser: Either[AppError, UserDomain] =
UserDomain.build(user.id, user.name)
}
@supermanue
supermanue / User.scala
Created April 5, 2022 06:14
User in adapter layer
import zio.experiment.domain.model.AppError
import zio.experiment.domain.model.User.{ User => UserDomain }
case class User(id: Int, name: String)
object User {
implicit class UserConversions(user: User) {
def toDomainUser: Either[AppError, UserDomain] =
UserDomain.build(user.id, user.name)
}
@supermanue
supermanue / sqlQueries.scala
Last active April 5, 2022 06:37
SQL Queries
import zio.experiment.adapter.model.{User => UserStored}
object SQL {
def get(id: Int): Query0[UserStored] =
sql"""SELECT * FROM USERS WHERE ID = $id """.query[UserStored]
def create(user: UserStored): Update0 =
sql"""INSERT INTO USERS (id, name) VALUES (${user.id}, ${user.name})""".update
import doobie.h2.H2Transactor
import scala.concurrent.ExecutionContext
import zio.Task
import zio.interop.catz._
object DoobiePersistenceService {
def mkTransactor(
conf: DbConfig,
connectEC: ExecutionContext,