Skip to content

Instantly share code, notes, and snippets.

@oldergod
Created September 18, 2019 13:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oldergod/5b86c7fe4ddc35127cfcb5a9ac7db69a to your computer and use it in GitHub Desktop.
Save oldergod/5b86c7fe4ddc35127cfcb5a9ac7db69a to your computer and use it in GitHub Desktop.
Android view events for tests
import com.jakewharton.rxrelay2.PublishRelay
import io.reactivex.Observable
import io.reactivex.Observer
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
/**
* [PublishRelay]-like [Observable] enforcing:
* 1. a unique observer at a time, and
* 2. that subscription happens on the main thread.
*
* In Android views, we bind our events with [RxBinding](https://github.com/JakeWharton/RxBinding).
* RxBinding enforces the two above listed conditions; but we lose those enforcement when doing
* testing in our abstracted JVM tests. [AndroidViewEvent] would allow unit tests to fail if a
* presenter violates any of the conditions `RxBinding` enforces.
*/
class AndroidViewEvent<VE : Any> private constructor() : Observable<VE>(), TestRule {
private val events = PublishRelay.create<VE>()
private var mainThreadId = -1L
private var subscribed = false
fun accept(viewEvent: VE) {
events.accept(viewEvent)
}
override fun subscribeActual(observer: Observer<in VE>) {
// Check main thread.
check(Thread.currentThread().id == mainThreadId)
check(!subscribed) { "Already subscribed to." }
subscribed = true
events.subscribe(observer)
}
override fun apply(
base: Statement,
description: Description
): Statement {
return object : Statement() {
override fun evaluate() {
mainThreadId = Thread.currentThread().id
base.evaluate()
}
}
}
companion object {
fun <VE: Any> create() = AndroidViewEvent<VE>()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment