TL; DR我有一个Task [Unit],在ScalaTest / FlatSpec中,测试任务在给定时间内是否成功的正确方法是什么?
我有一个具有服务器-客户端体系结构的应用程序,客户端与服务器之间的交互是不阻塞的。这是通过调用客户端返回的Future来实现的,该Future在服务器完成工作后完成。重要的是,此将来不会返回结果,而只是用来指示服务器已完成:
val notification: Task[Unit] = myServer.alterState("do this")
Await.result(notification.runAsync, 20.seconds)
我这里要测试的是服务器正确地将完成通知发送给客户端。我正在使用ScalaTest的FlatSpec对此进行测试,对我来说,以下似乎是有效的测试:
"Server" should "notify client upon completion" in {
val notification: Task[Unit] = myServer.alterState("do this")
Await.result(notification.runAsync, 20.seconds)
}
如果服务器的回复时间超过20秒,则Await.result将引发异常,该异常将被测试捕获并失败。
这是在Flatspec中执行这种测试的正确方法吗?所有匹配的框架似乎都围绕测试结果的值,并捕获预期的异常,但是我没有返回结果,我只是想测试未来是否成功结束。
答案 0 :(得分:1)
ScalaFutures
可以断言Future
在指定时间段内已准备就绪,例如
import org.scalatest._
import org.scalatest.concurrent.ScalaFutures
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
class ServerSpec extends FlatSpec with ScalaFutures {
"Server" should "notify client upon completion" in {
val notification: Task[Unit] = myServer.alterState("do this")
assert(notification.runAsync.isReadyWithin(20 seconds))
}
}
AsyncFlatSpec允许使用惯用的Scala语法,我们可以像这样在Future
上映射
import org.scalatest._
class ServerSpec extends AsyncFlatSpec {
"Server" should "notify client upon completion" in {
val notification: Task[Unit] = myServer.alterState("do this")
notification.runAsync.map(_ => succeed)
}
}
但是请确保服务器被设计为超时,否则测试将挂起。
FlatSpec
与Await
可以断言no exception应该这样抛出
import org.scalatest._
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
class ServerSpec extends FlatSpec with Matchers {
"Server" should "notify client upon completion" in {
val notification: Task[Unit] = myServer.alterState("do this")
noException should be thrownBy Await.result(notification.runAsync, 20.seconds)
}
}
我个人建议使用AsyncFlatSpec
方法。
答案 1 :(得分:0)
您可以使用intercept
方法来验证是否抛出了异常。
val notification: Task[Unit] = myServer.alterState("do this")
notification onComplete {
case Failure(_) => fail()
case Success(_) => succeed
}
intercept[TimeoutException] { //you can also use Exception instead of TimeoutException
Await.result(notification.runAsync, 20.seconds)
}
如果您的代码引发异常,则拦截将其捕获,然后进行测试 成功。 (您希望它引发异常,但确实如此。)