Как мне откатить интеграционный тест с Slick 3 + Specs2?
Я хочу написать несколько интеграционных тестов для службы, которая запускает Slick, а затем очищает базу данных postgresql вверх, откатывая транзакцию, но я не вижу способа сделать это. Я понимаю, что могу тестировать объекты DBIO, которые были скомпонованы вместе, и откатывать их назад, но не похоже, что это возможно, если я хочу протестировать на более высоком уровне абстракции.
В псевдокоде я хочу сделать это:
StartDbTransaction() // setup
DoSomethingInDB()
AssertSomething()
RollBackDbTransaction() // teardown
Например, если у меня есть это (упрощено изиграть-силуэт-скользкие семена):
class PasswordInfoDAO(db: JdbcBackend#DatabaseDef) {
// ...
def remove(loginInfo: LoginInfo): Future[Unit] =
db.run(passwordInfoSubQuery(loginInfo).delete).map(_ => ())
}
Я думал, что смогу написать черту ForEach по образцуРуководство по Specs2, который дает это общий пример:
// 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
}
}
Так что для гладких, я попробовал это:
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
}
Тогда я планировал использовать это примерно так:
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
}
}
}
Проблема в том, что пятно 3 будет игнорировать мой сеанс (по замыслу) и вместо этого будет использовать пул сеансов, поэтому мой откат ничего не сделает. Я думаю, что у Slick есть ожидание, что вы должны использовать его на уровне DBIOActions, которые могут быть скомпонованы вместе и, возможно, выполнены в разных контекстах. Slick 2 был способ контролировать сеанс с.withSession
, но это было удалено.
Является ли единственным вариантом создания, переноса и удаления тестовой базы данных с каждым тестом?