【问题标题】:Scala Test Async and Await methodsScala 测试 Async 和 Await 方法
【发布时间】:2026-02-09 13:40:01
【问题描述】:

我有一项使用 Scala Async 库的服务。我主要使用这个库来计时我的数据库调用。我要测试的方法包含使用异步等待机制对数据库的多次调用。我所拥有的伪代码如下:

def myDbMethod() = async {
  val firstCall = await(call the db and get the result)

  val secondCall = await(all the db and get the result)

  val thirdCall = await(all the db and get the result)
  ...
}

在我的 Scala 测试单元测试中,我有

Await.result(myDbMethod(), 10.seconds)

我只是试图通过运行我的单元测试来调试 myMethod,即使在进入 secondCall 之前,它也会返回测试成功。我的意思是我在对数据库的所有 3 次调用中都有断点,但是 IntelliJ 调试器会在它完成对数据库的第一次调用后立即退出。为什么是这样?如何使用 IntelliJ 调试器测试此行为?

【问题讨论】:

  • 这些方法是否相互依赖?还是没有关系?
  • 它们是相互依赖的,必须按顺序排列,这就是我必须使用这个库的原因

标签: scala asynchronous async-await


【解决方案1】:

我不确定我的回答是否能满足您的期望,但这是一个已知问题。问题是async/await 是一个相当复杂的宏,它对树进行大量转换(您可以通过启用-Xprint:<phase_name_after_typer> 标志来检查输出)。不幸的是,现有的 IDE(我正在使用 Intellij 和 Ensime)都不能调试它,但我不熟悉它们的内部结构来解释为什么它们不能详细说明。

根据我的经验,我找不到比原生 for-comprehension 更出色的优点,因此您可以坚持使用原生语法或显式 flatmap 调用,这可以很好地调试。

【讨论】:

  • 我在尝试使用 async / await 库时是否在自己的腿上开枪?该死。我需要找到一些方法来测试它!
  • @sparkr 你可以用Await 或scalatest whenReady 调用以通常的方式测试它们,但不能调试。另请注意,在您的 sn-p 期货中不会并行运行,请阅读最后一个示例 here
  • 每个调用都返回一个 Future。为什么你认为它不会并行运行?
  • @sparkr 就像你用理解来写它一样。请检查thisthis。为了并行运行它,您需要在变量中有一个未来并等待结果。
【解决方案2】:

此构造可用于依赖异步调用。 async / await 添加了一些糖以使其更容易,但是要手动将其正式化,您可以这样做:

def dbMethodDependant : Future[T] = for {
  res1 <- firstCall
  res2 <- secondCall(res2)
  res3 <- thirdCall(res3)
} yield res3

Await.result(dbMethodDependant, forever)

【讨论】: