Skip to content

Instantly share code, notes, and snippets.

@stig
Last active September 30, 2021 16:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stig/7997374 to your computer and use it in GitHub Desktop.
Save stig/7997374 to your computer and use it in GitHub Desktop.
Full source file for the PostgresSpec from my Scala/Slick/Pg unit testing blog post: https://www.brautaset.org/articles/2013/scala-slick-postgresql-unit-tests.html
package io.superloopy.test
import scala.slick.driver.PostgresDriver.simple._
import scala.slick.driver.PostgresDriver.SchemaDescription
import scala.slick.jdbc.{ StaticQuery => Q }
import org.scalatest.{ BeforeAndAfterEach, BeforeAndAfterAll, Suite }
import io.superloopy.util.DatabaseProvider
trait PostgresSpec extends Suite with BeforeAndAfterEach with BeforeAndAfterAll with DatabaseProvider {
this: { def ddl: SchemaDescription } =>
private val dbname = getClass.getSimpleName.toLowerCase
private val driver = "org.postgresql.Driver"
private def postgres = Database.forURL("jdbc:postgresql:postgres", driver = driver)
override def beforeAll() {
postgres withSession { implicit ss: Session =>
Q.updateNA(s"DROP DATABASE IF EXISTS $dbname").execute()
Q.updateNA(s"CREATE DATABASE $dbname").execute()
}
}
override def afterAll() {
postgres withSession { implicit ss: Session =>
Q.updateNA(s"DROP DATABASE $dbname").execute()
}
}
val database = Database.forURL(s"jdbc:postgresql:$dbname", driver = driver)
override def beforeEach() {
database withSession { implicit ss: Session =>
ddl.create
}
}
override def afterEach() {
database withSession { implicit ss: Session =>
ddl.drop
}
}
}
package io.superloopy.model.token
import org.joda.time.{ Duration, DateTime }
import scala.slick.driver.PostgresDriver.simple._
import java.util.UUID
import com.github.tototoshi.slick.JodaSupport._
import io.superloopy.util.DatabaseProvider
object PostgresTokenDao {
class Tokens(tag: Tag) extends Table[Token](tag, "token") {
def token = column[UUID]("token", O.PrimaryKey)
def userID = column[UUID]("user_id")
def created = column[DateTime]("created")
def expires = column[DateTime]("expires")
def * = (token, userID, created, expires) <> (Token.tupled, Token.unapply _)
}
val tokens = TableQuery[Tokens]
def ddl = tokens.ddl
}
trait PostgresTokenDao extends TokenDao {
this: DatabaseProvider =>
import PostgresTokenDao._
def findToken(token: UUID) = database.withSession { implicit ss: Session =>
tokens.findBy(_.token).firstOption(token)
}
def createToken(userID: UUID, validFor: Duration) = database.withSession { implicit ss: Session =>
val created = new DateTime
val expires = created.plus(validFor)
val token = UUID.randomUUID()
if (tokens.insert(Token(token, userID, created, expires)) == 1)
Some(token)
else
None
}
def deleteToken(token: UUID) = database.withSession { implicit ss: Session =>
tokens.withFilter(_.token === token).delete == 1
}
}
package io.superloopy.model.token
import org.scalatest.{ BeforeAndAfter, WordSpec }
import io.superloopy.test.PostgresSpec
import org.scalatest.matchers.MustMatchers
import scala.slick.jdbc.{ StaticQuery => Q }
import java.util.UUID
import org.joda.time.Duration
import scala.slick.driver.PostgresDriver.simple._
import io.superloopy.util.DatabaseProvider
class PostgresTokenDaoSpec extends WordSpec with PostgresSpec with MustMatchers with PostgresTokenDao {
def ddl = PostgresTokenDao.ddl
"createToken" should {
"create a record in the token table" in {
val userID = UUID.randomUUID()
createToken(userID, new Duration(3))
database.withSession { implicit ss: Session =>
Q.queryNA[Int]("select count(*) from public.token").first() must be(1)
}
}
"return the created token for current user" in {
val userID = UUID.randomUUID()
val duration = new Duration(232)
createToken(userID, duration) match {
case Some(token) => findToken(token).map(_.userID) must be(Some(userID))
case None => fail("Expected Some(token)")
}
}
}
"findToken" should {
"work" in {
val userID = UUID.randomUUID()
val token = createToken(userID, new Duration(3)).get
findToken(token) match {
case Some(Token(`token`, `userID`, _, _)) =>
case foo =>
println(foo)
fail()
}
}
}
"deleteToken" should {
"make sure token no longer exist" in {
val token = createToken(UUID.randomUUID(), new Duration(3)).get
deleteToken(token)
findToken(token) must be(None)
}
"not delete unrelated tokens" in {
val token = createToken(UUID.randomUUID(), new Duration(3)).get
deleteToken(UUID.randomUUID())
findToken(token) must be('defined)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment