Wie kann ich einen Integrationstest mit Slick 3 + Specs2 rückgängig machen?

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 rückgängig mache, aber ich sehe keine Möglichkeit, dies zu tun. Ich verstehe, dass ich zusammengesetzte DBIO-Objekte testen und zurücksetzen kann, aber es scheint nicht möglich zu sein, wenn ich auf einer höheren Abstraktionsebene testen möchte.

In Pseudocode möchte ich dies tun:

StartDbTransaction() // setup
DoSomethingInDB() 
AssertSomething() 
RollBackDbTransaction() // teardown

Zum Beispiel, wenn ich das habe (vereinfacht von der Play-Silhouette-Slick-Seed):

class PasswordInfoDAO(db: JdbcBackend#DatabaseDef) {

    // ...
    def remove(loginInfo: LoginInfo): Future[Unit] =
        db.run(passwordInfoSubQuery(loginInfo).delete).map(_ => ())

}

Ich dachte, ich könnte ein ForEach-Merkmal in Anlehnung an das @ schreib Specs2 Guide, dies ist ein allgemeines Beispiel:

// 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, ich habe Folgendes versucht:

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 habe ich geplant, es so zu benutzen:

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 Sitzung (von Entwurf) ignoriert und stattdessen einen Sitzungspool verwendet, sodass mein Rollback nichts bewirkt. Ich denke, dass Slick eine Erwartung hat, 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 @ zu steue.withSession, aber es wurde entfernt.

Ist die einzige Möglichkeit, mit jedem Test eine Testdatenbank zu erstellen, zu migrieren und zu löschen?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage