Scala 测试期货/可观测数据的接收观测值

Scala 测试期货/可观测数据的接收观测值,scala,rx-java,reactive-programming,scalatest,rx-scala,Scala,Rx Java,Reactive Programming,Scalatest,Rx Scala,我有: 我可以通过测试来测试输入列表是否确实传递给了可观察对象: val observable: Observable[Int] = Observable.from(List(5)) 其中materialevalues为: materializeValues(observable) should contain (5) 现在,如果我从未来创建一个可观察的对象,那么当测试超时时,我似乎不能对测试使用materialevalues。因此,如果我有: def materializeValues[T

我有:

我可以通过测试来测试输入列表是否确实传递给了可观察对象:

val observable: Observable[Int] = Observable.from(List(5))
其中
materialevalues
为:

materializeValues(observable) should contain (5)
现在,如果我从未来创建一个可观察的对象,那么当测试超时时,我似乎不能对测试使用
materialevalues
。因此,如果我有:

def materializeValues[T](observable: Observable[T]): List[T] = {
  observable.toBlocking.toIterable.toList
}
它超时且未通过测试。在具体化这两个观测值的过程中有什么不同,这导致我无法阻止它


另外,什么是测试可观察对象的idomatic方法?有没有办法不调用
toblock

我认为问题在于您使用了
AsyncWordSpecLike
(顺便问一下,为什么
AsyncWordSpecLike
而不是
AsyncWordSpecLike
AsyncWordSpecLike
/
AsyncWordSpec
旨在简化未来的测试。不幸的是,
Observable
是一个更强大的抽象,无法轻松映射到
未来的

特别是
AsyncWordSpecLike
/
AsyncWordSpec
允许您的测试返回
Future[Assertion]
。为了使之成为可能,它提供了自定义隐式
ExecutionContext
,可以强制执行所有操作,并知道所有计划的作业何时完成。但是,相同的自定义
ExecutionContext
是第二个代码不起作用的原因:只有在测试代码的执行完成后,计划作业的处理才会开始,但您的代码会在
futVal
上阻塞,因为您很不幸在
Future中注册了回调。onComplete
计划在
ExecutionContext
。这意味着你有一种自己的线程死锁

我不确定在Scala上测试
可观察性的官方方法是什么。在Java中,我认为这是推荐的工具。正如我所说的,
observatable
从根本上说比
Future
更强大,所以我认为测试
observatable
应该避免使用
AsyncWordSpecLike
/
AsyncWordSpec
。如果切换到使用
FlatSpec
WordSpec
,可以执行以下操作:

val futVal = Future.successful(5)
val observable: Observable[Int] = Observable.from(futVal)
materializeValues(observable) should contain(5)

我无法从
未来的
中复制
可观察的
超时的行为。可能您的隐式
ExecutionContext
存在一些问题?另外,提供一个始终是一个好主意。这里有一个要点:
ExecutionContext
来自
AsyncTestSuite
class MyObservableTestSpec extends WordSpec with Matchers {

  import scala.concurrent.ExecutionContext.Implicits.global
  val testValue = 5

  "observables" should {

    "be testable if created from futures" in {
      val futVal = Future.successful(testValue)
      val observable = Observable.from(futVal)

      val subscriber = TestSubscriber[Int]()
      observable(subscriber)
      subscriber.awaitTerminalEvent
      // now after awaitTerminalEvent you can use various subscriber.assertXyz methods
      subscriber.assertNoErrors
      subscriber.assertValues(testValue)
      // or you can use Matchers as 
      subscriber.getOnNextEvents should contain(testValue)
    }

  }

}