断言返回类型为Future [Unit]的scala方法的最佳方法是什么?

use*_*500 0 assert scala future scalatest

我有一个方法.此方法可能返回Future.failed(.....)或Future.successful(()).

def calculate(x:Int,y:Int):Future [Unit] = {........}

现在我需要测试这个方法.断言验证Future.successful(())案例的测试的最佳方法是什么 .

Ast*_*rid 7

Scalatest提供了一些使用Futures的方法.

选项1: isReadyWithin

import org.scalatest.concurrent.ScalaFutures._
import scala.concurrent.duration._

calculate(1, 3).isReadyWithin(1.second) should be(true)
Run Code Online (Sandbox Code Playgroud)

如果你想在这里做一些返回值,你可以使用whenReady:

implicit val patienceConfig = PatienceConfig(1.second)

def calculateWithResult(i: Int, j: Int): Future[Int] = ???

whenReady(calculateWithResult(1,3)) { result =>
    result should be(4)
}
Run Code Online (Sandbox Code Playgroud)

您需要一个隐含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
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

同样,您可以在此处针对结果运行测试.请注意,此变体意味着测试类中的每个测试都必须返回a Future,因此如果要混合同步和异步测试,则不是很好.我老实说也不确定如何AsyncXSpec选择超时值.

选项不要: Await.result

我建议不要使用,Await.result因为它会阻止线程持续时间.据我所知,上面两个选项的设计使得异步测试可以轻松并行运行.

注意事项:

在进行异步测试时,您希望对超时非常小心.太长了,如果出现问题,你的测试可能会持续多年.太短了,你的测试会很脆弱.并且程序可能在不同的环境中执行不同的操作,因此您可能会发现在本地计算机上完全足够的超时使构建服务器上的测试在5%的时间内失败.小心!