I have:
val observable: Observable[Int] = Observable.from(List(5))
and I can test that the input list is indeed passed on to the observable by testing:
materializeValues(observable) should contain (5)
where materializeValues
is:
def materializeValues[T](observable: Observable[T]): List[T] = {
observable.toBlocking.toIterable.toList
}
Now, if I create an observable from a future, I can't seem to use materializeValues
for the test as the test times out. So if I have:
val futVal = Future.successful(5)
val observable: Observable[Int] = Observable.from(futVal)
materializeValues(observable) should contain(5)
it times out and does not pass the test. What is different in the process of materializing these two observables, which leads to me not being able to block on it?
Also, what is the idomatic way of testing an observable? Is there any way of doing it without calling toBlocking
?
I think the problem is that you use
AsyncWordSpecLike
(by the way whyAsyncWordSpecLike
instead ofAsyncWordSpec
?).AsyncWordSpecLike
/AsyncWordSpec
are designed to simplify testingFuture
. UnfortunatelyObservable
is a more powerful abstraction that can't be easily mapped onto aFuture
.Particularly
AsyncWordSpecLike
/AsyncWordSpec
allow your tests to returnFuture[Assertion]
. To make it possible it provides custom implicitExecutionContext
that it can force to execute everything and know when all scheduled jobs have finished. However the same customExecutionContext
is the reason why your second code doesn't work: processing of the scheduled jobs starts only after execution of your test code has finished but your code blocks on thefutVal
because unlucklily for you callback registered inFuture.onComplete
is scheduled to be run on theExecutionContext
. It means that you have a kind of dead-lock with your own thread.I'm not sure what is the official way to test
Observable
on Scala. In Java I think TestSubscriber is the suggested tool. As I saidObservable
is fundamentally more powerful thing thanFuture
so I think to testObservable
you should avoid usingAsyncWordSpecLike
/AsyncWordSpec
. If you switch to useFlatSpec
orWordSpec
, you can do something like this: