在scalatest中创建和删除scala光滑表之前和之后的异步

我试图找出一种方法,在语句之前和之后具有异步,其中下一个测试用例直到测试用例内部的操作完成才运行.就我而言,它是在数据库中创建和删除表

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()
}

有了上述部分,就没有必要等待.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...