Je veux écrire des tests d'intégration pour un service qui exécute slick, puis nettoyer une base de données postgresql par la suite en annulant une transaction, mais je ne vois pas de moyen de le faire. Je comprends que je peux tester des objets DBIO qui ont été composés ensemble et les restaurer, mais il ne semble pas possible si je veux tester à un niveau d'abstraction plus élevé.Comment annuler un test d'intégration avec Slick 3 + Specs2?
En pseudocode, je veux faire:
StartDbTransaction() // setup
DoSomethingInDB()
AssertSomething()
RollBackDbTransaction() // teardown
Par exemple, si j'ai (simplifié du play-silhouette-slick-seed):
class PasswordInfoDAO(db: JdbcBackend#DatabaseDef) {
// ...
def remove(loginInfo: LoginInfo): Future[Unit] =
db.run(passwordInfoSubQuery(loginInfo).delete).map(_ =>())
}
Je pensais que je pourrais écrire un trait PourChaque le long les lignes du Specs2 Guide, qui donne à ce un exemple générique:
// a transaction with the database
trait Transaction
trait DatabaseContext extends ForEach[Transaction] {
// you need to define the "foreach" method
def foreach[R: AsResult](f: Transaction => R): Result = {
val transaction = openDatabaseTransaction
try AsResult(f(transaction))
finally closeDatabaseTransaction(transaction)
}
// create and close a transaction
def openDatabaseTransaction: Transaction = ???
def closeDatabaseTransaction(t: Transaction) = ???
}
class FixtureSpecification extends mutable.Specification with DatabaseContext {
"example 1" >> { t: Transaction =>
println("use the transaction")
ok
}
"example 2" >> { t: Transaction =>
println("use it here as well")
ok
}
}
Donc, pour marée noire, j'ai essayé ceci:
override def foreach[R: AsResult](f: JdbcBackend#DatabaseDef => R): Result = {
val db = dbConfig.db
val session = db.createSession()
session.conn.setAutoCommit(false)
val result = AsResult(f(db))
session.conn.rollback()
result
}
Alors je comptais l'utiliser un peu comme ceci:
class PasswordInfoDAOSpec(implicit ee: ExecutionEnv)
extends Specification with DatabaseContext {
"password" should {
"be removed from db" in { db =>
// arrange
db.run(...) // something to set up the database
// act
PasswordInfoDAO(db).remove(loginInfo).await
// assert
PasswordInfoDAO(db).find(loginInfo) must be None.await
}
}
}
Le problème est que lisse 3 ignorera ma session (par la conception) et plutôt utiliser un pool de sessions, donc mon roll-back ne fait rien. Je pense que Slick s'attend à ce que vous l'utilisiez au niveau de DBIOActions qui peut être composé ensemble et éventuellement exécuté dans des contextes différents. Slick 2 avait un moyen de contrôler la session avec .withSession
, mais il a été supprimé.
La seule option pour créer, migrer et supprimer une base de données de test avec chaque test?