我创建了一个简单的测试场景,显示了以下内容:
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。我总结了以下要点。
在JVM上使用ScalaTest的串行执行上下文将确保产生从测试主体返回的Future [Assertion]的相同线程也用于执行在执行测试主体时赋予执行上下文的任何任务,并且该线程不会在测试完成之前,可以执行其他任何操作。
但是,这种线程限制策略的确意味着,当您在JVM上使用默认执行上下文时,必须确保不要在测试主体中阻塞,以等待任务由执行上下文完成。如果您阻止,则测试将永远无法完成。
解决方案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)
}
}
}
异步样式特征提供serial execution context
private final val serialExecutionContext: ExecutionContext = new concurrent.SerialExecutionContext
implicit def executionContext: ExecutionContext = serialExecutionContext
只是将作业放在队列中,并使用主线程一个接一个地执行它们,也就是说,只有一个线程可用。因此,在任何时候阻塞该线程都会阻塞整个测试套件。但是请注意,对于以下three reasons],此选择为根据设计
因此,用线程池支持的执行上下文替换串行执行上下文可能会导致进行flakey测试,以换取没有真正的性能提升。
我在https://stackoverflow.com/a/55526334/5205022提供了一个示例和一些相关信息