Desidero scrivere alcuni test di integrazione per un servizio che esegue slick e quindi pulire un database postgresql in seguito ripristinando una transazione, ma non vedo un modo per farlo. Capisco che posso testare gli oggetti DBIO che sono stati composti insieme e rotoli indietro, ma non sembra possibile se voglio testare a un livello più alto di astrazione.Come posso eseguire il rollback di un test di integrazione con Slick 3 + Specs2?
In pseudocodice, voglio fare questo:
StartDbTransaction() // setup
DoSomethingInDB()
AssertSomething()
RollBackDbTransaction() // teardown
Per esempio, se ho questo (semplificato dal play-silhouette-slick-seed):
class PasswordInfoDAO(db: JdbcBackend#DatabaseDef) {
// ...
def remove(loginInfo: LoginInfo): Future[Unit] =
db.run(passwordInfoSubQuery(loginInfo).delete).map(_ =>())
}
ho pensato che avrei potuto scrivere un tratto ForEach lungo le linee del Specs2 Guide, che fornisce un esempio generico:
// 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
}
}
Così, per slick, ho provato questo:
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
}
Poi ho pensato di usarlo un po 'come questo:
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
}
}
}
Il problema è che liscia 3 sarà ignorare la mia sessione (in base alla progettazione) e di utilizzare invece un pool di sessioni, quindi il mio rollback non fa nulla. Penso che Slick abbia l'aspettativa che dovresti usarlo a livello di DBIOActions che può essere composto insieme ed eventualmente eseguito in diversi contesti. Slick 2 aveva un modo per controllare la sessione con .withSession
, ma è stata rimossa.
È l'unica opzione per creare, migrare e rilasciare un database di test con ogni test?