Last active
September 30, 2021 16:07
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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