dvdciri
dvdciri

Reputation: 451

PublishSubject does not work with firstOrError()

Can someone please explain me why PublishSubject is not working nicely with firstOrError()?

I'm expecting firstOrError to return a NoSuchElementException when the PublishSubject is created without any value.

I wrote some tests in order to better explain the problem:

@Test
fun `test one`() {
    // THIS TEST FAILS
    val publishSubject = PublishSubject.create<Boolean>()

    val testSubscriber = publishSubject
        // .toFlowable(BackpressureStrategy.LATEST) // With or without this doesn't make any difference
        .firstOrError()
        .test()

    testSubscriber
        .assertNotComplete()
        .assertError(NoSuchElementException::class.java)
}

@Test
fun `test two`() {
    // THIS TEST PASSES
    val flowable = Flowable.empty<Boolean>()

    val testSubscriber = flowable
        .firstOrError()
        .test()

    testSubscriber
        .assertNotComplete()
        .assertError(NoSuchElementException::class.java)
}

Upvotes: 2

Views: 2455

Answers (1)

michalbrz
michalbrz

Reputation: 3494

Short version: Flowable emits no element and completes whereas PublishSubject emits no element and doesn't complete.

Long version:

You assume that PublishSubject.create<Boolean>() is equivalent to Flowable.empty<Boolean>(). But they are not.

First, let's see what firstOrError() really does:

Returns a Single that emits only the very first item emitted by this Observable or signals a NoSuchElementException if this Observable is empty.

So you it makes sense that Flowable.empty<Boolean>() works, because it's, well, empty. What does it mean "empty"?

Returns a Flowable that emits no items to the Subscriber and immediately invokes its onComplete method.

I emphasized important fragment. Flowable.empty() calls onComplete whereas PublishSubject.create() just creates Subject which waits for calling onNext() on him or for subscribers.

So Flowable.empty() is empty, but PublishSubject.create() is not empty. It doesn't call onComplete. See PublishSubject docs for more info.

If you want to have empty PublishSubject, simply call PublishSubject.empty<Boolean>().

Upvotes: 3

Related Questions