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

时间:2018-07-06 12:01:18

标签: scala future assert scalatest

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

def计算(x:整数,y:整数):未来[单位] = { ........ }

现在我需要测试此方法。为验证Future.successful(())情况的测试断言的最佳方法是什么。

3 个答案:

答案 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

AsyncFlatSpecFreeSpec等特征有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,否则我们不必显式检查它。