为什么我的 Scala 异步测试在我执行 Await.result 时永远不会完成?

Why my Scala Async test never completes when I do Await.result?

我创建了一个简单的测试场景来展示这一点:

class Test extends AsyncFunSuite {

  test("async test") {
    val f = Future {
      val thread = new Thread {
        override def run(): Unit = {
          println("OKAYY")
        }
      }
      thread.start()
    }

    Await.result(f, Duration.Inf)
    Future {
      assert(true)
    }
  }

}

执行此操作时,测试将永远运行并且永远不会完成。

您将在 ScalaTest(AsyncFeatureSpec、AsyncFlatSpec、AsyncFreeSpec、AsyncFunSpec、AsyncFunSuite、AsyncWordSpec)中看到相同的行为。

这是因为ScalaTest默认的执行上下文是串行执行上下文。您可以在此处阅读更多相关信息:https://www.scalatest.org/user_guide/async_testing。我总结了以下要点。

Using ScalaTest's serial execution context on the JVM will ensure the same thread that produced the Future[Assertion] returned from a test body is also used to execute any tasks given to the execution context while executing the test body—and that thread will not be allowed to do anything else until the test completes.

This thread confinement strategy does mean, however, that when you are using the default execution context on the JVM, you must be sure to never block in the test body waiting for a task to be completed by the execution context. If you block, your test will never complete.

解决方案 1:覆盖执行上下文

implicit override def executionContext = scala.concurrent.ExecutionContext.Implicits.global

解决方案 2:链接

class Test extends AsyncFunSuite {

  test("async test") {
    val f = Future {
      val thread = new Thread {
        override def run(): Unit = {
          println("OKAYY")
        }
      }
      thread.start()
    }

    f.map { _ =>
      assert(true)
    }
  }

}