Ich möchte einige Integrationstests für einen Dienst schreiben, der glatt läuft, und anschließend eine postgresql-Datenbank bereinigen, indem ich eine Transaktion zurückbringe, aber ich sehe keinen Weg, dies zu tun. Ich verstehe, dass ich zusammengesetzte DBIO-Objekte testen und zurückrollen kann, aber es sieht nicht so aus, als ob es möglich ist, auf einer höheren Abstraktionsebene zu testen.Wie kann ich einen Integrationstest mit Slick 3 + Specs2 rückgängig machen?
In Pseudo-Code, möchte ich dies tun:
StartDbTransaction() // setup
DoSomethingInDB()
AssertSomething()
RollBackDbTransaction() // teardown
Zum Beispiel, wenn ich dies (aus dem play-silhouette-slick-seed vereinfacht):
class PasswordInfoDAO(db: JdbcBackend#DatabaseDef) {
// ...
def remove(loginInfo: LoginInfo): Future[Unit] =
db.run(passwordInfoSubQuery(loginInfo).delete).map(_ =>())
}
Ich dachte, ich entlang einer foreach Charakterzug schreiben konnte die Zeilen der Specs2 Guide, die dies ein generisches Beispiel gibt:
// 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
}
}
Also für Slick, habe ich versucht, dies:
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
}
Dann wollte ich es benutzen Art wie folgt aus:
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
}
}
}
Das Problem ist, dass Slick 3 meine Session (mit Absicht) ignoriert und stattdessen ein Sitzungspool, sodass mein Roll-Back nichts bewirkt. Ich denke, dass Slick erwartet, dass Sie es auf der Ebene von DBIOActions verwenden sollten, die zusammen komponiert und möglicherweise in verschiedenen Kontexten ausgeführt werden können. Slick 2 hatte eine Möglichkeit, die Sitzung mit .withSession
zu steuern, aber es wurde entfernt.
Ist die einzige Option zum Erstellen, Migrieren und Löschen einer Testdatenbank mit jedem Test?