【问题标题】:Scala testing with fire and forget FuturesScala 测试与火并忘记期货
【发布时间】:2016-06-09 08:45:06
【问题描述】:

所以我有一些带有端点的服务器代码,我想在其中异步运行东西。为此,我正在使用期货。有些任务会导致结果,但也有昂贵的 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 可以完成。但是当我测试时,测试结束并且里面的任务开始抛出,因为他们使用的服务变得不可用。

所以问题是:我如何等待这些火灾并忘记未来而不阻塞我的主要执行?

【问题讨论】:

  • 你肯定要阻止主执行。
  • 能否也粘贴测试代码。
  • @Nyavro 我真的不想那样做。错误记录在服务器上,不需要传播到客户端。如果我等待 IO,我们正在讨论增加 3-5 秒的响应时间。
  • 我想告诉执行上下文等待它运行的任务
  • 你使用哪个测试框架?

标签: scala concurrency future


【解决方案1】:

为了说明我的答案,让我们假设您访问一些 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,并在测试中等待它。

【讨论】:

    猜你喜欢
    • 2013-04-27
    • 1970-01-01
    • 2020-11-05
    • 2021-09-17
    • 2015-08-25
    • 2015-02-12
    • 2012-10-17
    • 1970-01-01
    • 2020-10-10
    相关资源
    最近更新 更多