我有办法。此方法可能返回Future.failed(.....)或Future.successful(())。
def计算(x:整数,y:整数):未来[单位] = { ........ }
现在我需要测试此方法。为验证Future.successful(())
情况的测试断言的最佳方法是什么。
答案 0 :(得分:6)
Scalatest提供了使用Future
的几种方法。
选项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%。小心!
答案 1 :(得分:1)
至少两个选项:
Await.result
,然后通过断言某些内容来确保结果是您期望的结果。AsyncFlatSpec
之类的东西进行测试。答案 2 :(得分:0)
我假设您已经在测试类中扩展了ScalaFutures
,并且已根据需要配置了超时(patienceConfig
)。如果这样做,则可以使用以下方法之一:
whenReady(calculate(1,3))(_ => succeed)
或
whenReady(calculate(1,3))(_ shouldBe ())
第一种方法是可取的,因为Unit
不能有任何其他值,因此除非代码出于某种原因返回null
,否则我们不必显式检查它。