Scala测试用火和忘记期货

时间:2016-06-09 08:45:06

标签: scala concurrency future

所以我有一些端点的服务器代码,我想异步运行东西。为此,我使用了期货。有一些任务导致了结果,但也有昂贵的IO任务,所以我在火中执行它们并忘记了Future,如下:

import scala.concurrent.Future

val ec = scala.concurrent.ExecutionContext.global

Future {
  Thread.sleep(10000)
  println("Done")
}(ec)

println("Exiting now")

输出是:

import scala.concurrent.Future

ec: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl@2315ca48

res0: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise@7d1e50cb

Exiting now
res1: Unit = ()

通常在服务器上这不是一个大问题,因为上下文在接收其他任务时继续运行,因此IO可以完成。但是当我测试时,测试结束并且内部的任务开始抛出,因为他们使用的服务变得不可用。

所以问题是:如何在不阻止主要执行的情况下等待这些火灾并忘记期货?

1 个答案:

答案 0 :(得分:2)

为了说明我的答案,让我们假设您访问了一些fileService以在即发即弃的部分加载文件,并且您使用Mockito(或其他模拟框架,这个想法保持不变)为您的单位试验。然后,我将在我的解释中提到的代码看起来像这样:

class SystemUnderTest(val fileService: MyFileService) {
  def testedMethod(): GoodResult = {
    val file = // ... some logic to extract file ...
    Future {
      fileService.uploadFile(file)
    }
    // ... other logic returning an instance of GoodResult
  }
}

然后,在org.scalatest.Eventually的测试组合中,做出如下的断言:

eventually {
  verify(fileService).uploadFile(any())
}

它将确保主进程在可以验证已调用上传器服务(或implicit patienceConfig定义的超时已过期)之前不退出。

当然,您总是可以选择在生产代码中返回您不等待的Future,并在测试中等待它。