【问题标题】:Testing values returned by 2 Futures are equal to each other2 个 Future 返回的测试值相等
【发布时间】:2021-06-21 15:49:07
【问题描述】:

为了测试 Scala 未来值,我使用以下代码:

  "Simple Test" should "Test Future" in {

    val futureData1: Future[Data] = MakeData()

    futureData1 map { data => { 
      assert(data.value == 2)
    }
    }
  }

这符合预期,如何测试两个 Futures 中包含的值?

例如,如何正确修改下面测试两个Futures:

  "Simple Test" should "Test Future" in {

    val futureData1: Future[Data] = MakeData()
    val futureData1: Future[Data] = MakeData()

    futureData1 map { data => {
      futureData1 map { data2 => {
        assert(data.value == data2.value)
      }
      }
    }
    }
  }

阅读 https://www.scalatest.org/user_guide/async_testing ,似乎没有描述多个 Futures 测试的文档。

【问题讨论】:

  • 第一个map 应该是flatMap,使用for 可能会更好

标签: scala future scalatest


【解决方案1】:

像这样使用map 不太可能按照您希望的方式工作 - map 内部的断言在未来完成之前不会运行,这可能会在测试已经完成之后发生,即使没有,来自 assert 的异常将被包装到未来中,并且不会真正抛出到主线程上,因此测试将始终通过。

您似乎正在使用 scalatest,因此,混入 Eventually 可能是有意义的,这样您就可以执行这些断言属性:

    val f = doStuff()
    eventually {
      f.value shouldBe Some(Data(2))
    }

或者,如果您更喜欢 ScalaFutures 语义(混合使用 ScalaFutures 而不是 Eventually),您可以这样做:

    val f = doStuff()
    whenReady(f) { data => assert(data.value == 2) }

或者只是

    assert(doStuff().futureValue.value == 2) 

这也使您的问题的答案非常明显:

    assert(future1.futureValue == future2.futureValue)

如果您仍在寻找将多个期货组合在一起的方法,您可以使用.zip(用于两个期货)或.sequence(用于任意数字):

    whenReady(future1 zip future2) { case (d1, d2) => assert(d1 == d2) }
    whenReady(Future.sequence(List(f1, f2, f3, f4)) { case first :: rest => 
        assert(rest.forall(_ == first))

【讨论】:

  • 或者您只使用 ScalaTest 提供的异步规范,期望 Future[Assertion] 并使用简单的 for
  • 或者……我讨厌 scalatest 是 itllthatbit 提供了太多不同的方法来做同样的事情。
猜你喜欢
  • 2015-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 2022-12-09
  • 2017-08-02
  • 2020-03-20
相关资源
最近更新 更多