在将来使用的情况下ScalaTest中的afterAll()问题

时间:2017-05-19 16:43:33

标签: scala scalatest

在我的ScalaTest套件结束时,我需要做一些数据库清理。 清理本身是Future。该套件不会调用super.afterAll(),这会使套件使用的某些资源(如Web浏览器和数据库连接)等待处理。

以下是相关的代码:

override def afterAll():Unit={
    var cleanUpsInProgress = true
    DB.cleanUpDeletedSegments(db).onComplete{case _ =>
      cleanUpsInProgress = false
    }
    while(cleanUpsInProgress){}
    db.close()
    aggregatesDB.close()
    super.afterAll()
  }

def cleanUpDeletedSegments(implicit db:ADMPDB):Future[Int]={
  db.run{
    segments.filter(_.deleted === 1).delete
  }
}

我已经调试了一段时间,并且得知结论它甚至没有在将来的onComplete回调中处理代码。即使我用存根Future.successfull(1)替换Slick的数据库操作,我仍然有一切未决并且super.afterAll()未被调用。 可能我做了一些愚蠢的错事?你能帮忙吗?

注意:我也认为我需要在这里使用这个丑陋的varwhile循环,因为否则主线程将完成,启动套件运行的框架将关闭JVM。也许我错了,所以听听一些评论会很棒。

-------------------------- UPDATE -------------------- -

泰勒的解决方案有效。但是当我flatMap再次进行asynch清理(我实际上需要做)时,问题又是一样的。以下代码冻结,不会调用super.afterAll

override def afterAll():Unit={
  val cleanUp = DB.cleanUpDeletedSegments(db).flatMap(_ => DB.cleanUpDeletedSegmentGroups(db))
  Await.result(cleanUp, 6 seconds)
  db.close()
  aggregatesDB.close()
  super.afterAll()
} 

Await.result也不会抛出TimeoutException,而是从我看不到正常完成的内容。有什么想法吗?

只有在我为每个未来按顺序使用Await.result时,它才有效:

override def afterAll():Unit={
  val cleanUpSegments = DB.cleanUpDeletedSegments(db)
  Await.result(cleanUpSegments, 3 seconds)
  val cleanUpSegmentGroups = DB.cleanUpDeletedSegmentGroups(db)
  Await.result(cleanUpSegmentGroups, 3 seconds)
  db.close()
  aggregatesDB.close()
  super.afterAll()
}

2 个答案:

答案 0 :(得分:3)

await清理完成Future可能更容易:

import scala.concurrent.Await
import scala.concurrent.duration._

override def afterAll() ={
  val future = DB.cleanUpDeletedSegments(db)
  Await.result(future, 2 minutes)
  aggregatesDB.close()
  super.afterAll()
}

您可以将超时设置为合理的

答案 1 :(得分:2)

使用@Tyler的解决方案。您的解决方案无效,因为您使用了来自多个线程的非易失性变量cleanupInProgress