当前位置: 首页 > 知识库问答 >
问题:

Scala中期货的单元测试失败

余弘毅
2023-03-14

我试图在我正在编写的脚本中测试错误处理。如果异步函数fetchBar失败,我将模式匹配失败案例,然后返回包含失败结果的成功未来。

val fetchedBar = Try(fooClient.fetchBar(params))

fetchedBar match {
  case Success(bar) => foobar(bar)
  case Failure(e) => Future.successful(FooResult(success = false))
}

然而,当我对这个流进行单元测试时,我在测试失败案例时遇到了麻烦。我在fetchBar上打了一个存根,以返回失败的future,如下所示。

val fetchedBar = Try(Future.failed(new Exception()))

但是我注意到fetchedBar返回的是成功而不是失败。为什么会这样,我如何存根fetchBar函数来创建一个失败的尝试?

共有1个答案

松雅健
2023-03-14

我认为你稍微混淆了概念——但这不完全是你的错。

事实是,Scala中的< code>Future是一个有点非正交的概念——事实上,它不仅代表延迟执行的概念,也代表失败的概念。

正因为如此,在大多数情况下,将未来包装到尝试中没有多大意义,反之亦然——除非有人想明确地将失败的概念与异步的概念分开。

换句话说,下面的组合有点奇怪,但仍然有其用途:

  1. 尝试[Future[_]]-Future已经捕获了失败。但是,如果您有一个(行为不佳)库方法通常返回Future,但可能会抛出一个“同步”路径,则这是有意义的:
def futureReciprocal(i: Int): Float = { 
   val reciprocal = 1 / i // Division by zero is intentional
   Future.successful(reciprocal)
}

futureReciprocal(0) // throws
Try(futureReciprocal(0)) // Failure(DivisionByZero(...))

...但这基本上是修复实现不佳函数的一种变通方法

在你的情况下,你想做的是断言未来的结果。要做到这一点,实际上至少有两种选择。

    < li >阻塞直到未来完成并检查结果-这通常是通过< code > Scala . concurrent . await :完成的
// writing this without the compiler, might mix up namespaces a bit
import scala.concurrent.Await
import scala.concurrent.duration.DurationInt

val future = fooClient.fetchBar(...)
val futureResult: Try[_] = Await.result(future, 1.second)
futureResult match { case Success(_) => ??? ; case Failure(exc) => ???; }
class YourTest extends FlatSpec with ScalaFutures {
   "fetchBar should return failed future" in {
        val future: Future[XYZ] = fooClient.fetchBar(...)
        // whenReady comes from the ScalaFutures trait
        whenReady(future) { result => result shouldBe XYZ } // asserting on the successful future result
        whenReady(future.failed) { exc => exc shoulBe a[RuntimeException] } // asserting on an exception in the failed future
   }
}
 类似资料:
  • 我参考DataframeGenerator示例编写了单元测试,该示例允许您动态生成模拟dataframes 在成功执行以下命令后 在运行以下命令之一时,我会得到输出中显示的错误 输出 null null EDIT-1 My unit-test类包含以下几个方法 而如下所示

  • 我使用 并行运行 2 个期货。我想知道在所有情况下哪个成功了,哪个失败了(所有情况都应该运行到完成,并显示结果或失败状态)。目前,我只能检索到综合成功结果 我从这里开始操作,但这还不够,因为我无法获得单个失败时的成功状态,也无法获得两个失败时的失败状态。在Scala未来的理解中,两个失败都是失败的 我试图避免这种混乱: 编辑:另一个版本-这是一个有效的方法吗?

  • 问题内容: 如何在JUnit 4中将测试标记为预期的失败? 在这种情况下,我想继续运行此测试,直到上游修补了某些内容。忽略测试有点太过分了,因为我可能会忘记它。我也许可以添加注释并捕获由引发的异常,但这似乎也与预期的行为有关。 这是我当前的测试结果: 该断言应该会成功,但是由于上游错误,它不会成功。然而,这个测试是正确的。它应该成功。实际上,我发现的所有替代方案都具有误导性。现在,我认为这是我最好

  • 我不熟悉匕首。我创建了一个非常简单的单元测试,试图理解我应该如何使用dagger。不幸的是,它失败了。我可能还不了解匕首的一些基本原理。 而我的测试课失败了 我认为dagger会将B注入A,因为A希望注入B,DaggerModule包含一个@Providers注释方法,该方法创建B。 更新: 我发现当我像这样编写模块类时 将B注入A作品中。然而,我不理解为什么当模块有一个构造a实例的带注释的方法时

  • 在试验并发执行时,我想知道如何实际测试它。执行流程具有副作用性质,创建未来是为了包装独立的执行/处理。 我一直在寻找一些关于如何正确单元测试的好例子,下面的场景(和是我希望测试的方法): 情景#1 情景动机 立即返回,但调用两个执行单独任务的未来(例如,保存分析并将记录存储到数据库)。这些服务调用可以被模拟,但我试图测试的是,一旦我将它们包装在s中,这两个服务都会被调用 场景#2 情景动机 从可以

  • 我不熟悉Scala中的单元测试,我找不到一种方法来存根单例对象中定义的函数。 例如: 我试图对Profile类中定义的函数进行单元测试。因为我不想在单元测试中通过web实际访问外部API,所以我尝试存根对象及其函数以返回一些预定义的值。 我研究了ScalaMock、EasyMock和Mockito框架,但找不到一种方法来存根单例对象的方法。ScalaMock状态 为什么所有的模拟框架都不提供这种功