Scalatest 提供了几种使用 Futures 的方法。
选项 1: isReadyWithin
import org.scalatest.concurrent.ScalaFutures._
import scala.concurrent.duration._
calculate(1, 3).isReadyWithin(1.second) should be(true)
如果你想在这里做一些返回值的事情,你可以使用whenReady:
implicit val patienceConfig = PatienceConfig(1.second)
def calculateWithResult(i: Int, j: Int): Future[Int] = ???
whenReady(calculateWithResult(1,3)) { result =>
result should be(4)
}
你需要一个隐含的PatienceConfig 在范围内告诉whenReady 何时因为超时而使测试失败。我相信scalatest 库之一中有一个默认的库,但选择的时间段很短——大约 10 毫秒——并且通常会导致不稳定的测试。
选项 2: AsyncXSpec
有Async 变体FlatSpec、FreeSpec、FunSpec 等特征。它们的工作原理与它们的同步变体非常相似,只是现在任何测试都必须返回 Future[Assertion] 类型的值。例如:
class Test extends AsyncFreeSpec {
"An asynchronous method" - {
"should succeed" in {
calculate(1,3).map { _ =>
// just want to make sure the future completes
succeed
}
}
}
}
同样,您可以在此处针对结果运行测试。请注意,此变体意味着您的测试类中的每个 测试都必须返回一个Future,因此如果您想混合同步和异步测试,这并不好。老实说,我也不确定AsyncXSpec 是如何选择其超时值的。
选项不要: Await.result
我建议不要使用Await.result,因为它会在持续时间内阻塞线程。据我所知,上述两个选项的设计目的是让异步测试可以轻松并行运行。
注意事项:
在进行异步测试时,您需要格外小心超时。时间太长,如果出现问题,您的测试最终可能会挂起很长时间。太短了,你的测试会很不稳定。并且程序在不同的环境中可能会执行不同的操作,因此您可能会发现在本地计算机上完全足够的超时会使构建服务器上的测试失败 5% 的时间。小心!