我试图找出一种方法,在语句之前和之后具有异步,其中下一个测试用例直到测试用例内部的操作完成才运行.就我而言,它是在数据库中创建和删除表
val table = TableQuery[BlockHeaderTable] val dbConfig: DatabaseConfig[PostgresDriver] = DatabaseConfig.forConfig("databaseUrl") val database: Database = dbConfig.db before { //Awaits need to be used to make sure this is fully executed before the next test case starts //TODO: Figure out a way to make this asynchronous Await.result(database.run(table.schema.create),10.seconds) } "BlockHeaderDAO" must "store a blockheader in the database,then read it from the database" in { //... } it must "delete a block header in the database" in { //... } after { //Awaits need to be used to make sure this is fully executed before the next test case starts //TODO: Figure out a way to make this asynchronous Await.result(database.run(table.schema.drop),10.seconds) }
有没有一种简单的方法可以删除我之前和之后函数中的这些Await调用?
解决方法
以下是Dennis Vriend在其
slick-3.2.0-test项目中采用的测试方法.
首先,定义dropCreateSchema方法.此方法尝试创建表;如果该尝试失败(例如,因为该表已经存在),它将删除,然后创建表:
def dropCreateSchema: Future[Unit] = { val schema = BlockHeaderTable.schema db.run(schema.create) .recoverWith { case t: Throwable => db.run(DBIO.seq(schema.drop,schema.create)) } }
其次,定义一个createEntries方法,该方法使用一些示例数据填充表,以便在每个测试用例中使用:
def createEntries: Future[Unit] = { val setup = DBIO.seq( // insert some rows BlockHeaderTable ++= Seq( BlockHeaderTableRow(/* ... */),// ... ) ).transactionally db.run(setup) }
第三,定义一个初始化方法,按顺序调用上述两个方法:
def initialize: Future[Unit] = for { _ <- dropCreateSchema _ <- createEntries } yield ()
在测试类中,混合ScalaFutures
特征.例如:
class TestSpec extends FlatSpec with Matchers with ScalaFutures with BeforeAndAfterAll with BeforeAndAfterEach { // ... }
同样在测试类中,定义从Future到Try的隐式转换,并覆盖beforeEach方法以调用initialize:
implicit val timeout: Timeout = 10.seconds implicit class PimpedFuture[T](self: Future[T]) { def toTry: Try[T] = Try(self.futureValue) } override protected def beforeEach(): Unit = { blockHeaderRepo.initialize // in this example,initialize is defined in a repo class .toTry recover { case t: Throwable => log.error("Could not initialize the database",t) } should be a 'success } override protected def afterAll(): Unit = { db.close() }
有了上述部分,就没有必要等待.