簡體   English   中英

Scala 中 Futures 的單元測試失敗

[英]Unit Testing failures from Futures in Scala

我正在嘗試在我正在編寫的腳本中測試錯誤處理。 如果異步函數 fetchBar 失敗,我會匹配失敗案例,然后返回一個包含失敗結果的成功未來。

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

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

但是,當我對這個流程進行單元測試時,我在測試失敗案例時遇到了麻煩。 我已經存根 fetchBar 返回一個失敗的未來,如下所示。

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

但我注意到 fetchedBar 返回的是 Success 而不是 Failure。 為什么會這樣,我如何存根 fetchBar 函數來創建失敗的 Try?

我認為你有點混淆概念 - 但這不是 100% 你的錯。

問題是,Scala 中的Future是一個有點非正交的概念——也就是說,它不僅代表了延遲執行的概念,還代表了一個失敗的概念。

因此,在大多數情況下,將 Future 包裝到 Try 中沒有多大意義,反之亦然 - 除非人們想明確地將失敗的概念與異步的概念分開。

換句話說,以下組合有點奇怪,但仍然有用:

  1. Try[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(...))

...但這基本上是一種解決實現不佳功能的方法

  1. Future[Try[_]] - 有時有助於將“業務”錯誤(由Future.success(Failure(...)) )與“基礎設施”故障(由Future.failed(...)Future.failed(...) 一方面 - 這對於 akka-streams 尤其有用,它傾向於將失敗的期貨視為對流來說是“致命的”。

在您的情況下,您想要做的是斷言未來的結果 要做到這一點,實際上您至少有兩個選擇。

  1. 阻塞直到未來完成並檢查結果 - 這通常用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) => ???; }
  1. 使用一些支持使用期貨的測試框架 - 例如 scalatest:
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
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM