首页 > 解决方案 > 断言返回类型为 Future[Unit] 的 scala 方法的最佳方法是什么

问题描述

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

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

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

标签: scalafutureassertscalatest

解决方案


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等特征。它们的工作原理与它们的同步变体非常相似,只是现在任何测试都必须返回 type 的值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测试都必须返回 a ,因此如果您想混合同步和异步测试,那就不好了。老实说,我也不确定如何AsyncXSpec选择它的超时值。

选项不要: Await.result

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

注意事项:

在进行异步测试时,您需要非常小心超时。时间太长,如果出现问题,您的测试最终可能会挂起很长时间。太短了,你的测试会很不稳定。并且程序在不同环境中的执行可能会有所不同,因此您可能会发现在本地计算机上完全足够的超时会使构建服务器上的测试失败 5% 的时间。当心!


推荐阅读