Dispatch
Simple CoroutineDispatcher injection
CoroutineDispatcher Injection
Change dispatchers without referencing a singleton or injecting a custom object. The dispatchers are a property of the CoroutineScope
itself, so it's easy to inject custom dispatchers for testing.
fun updateUI() = coroutineScope.launchMain { /* ... */ }
val somethingDeferred = coroutineScope.asyncDefault { /* ... */ }
suspend fun fetchData() = withIO { /* ... */ }
val state = flow { /* ... */ }.flowOnIO()
Test Utilities
Dispatch's TestProvidedCoroutineScope
is just aTestCoroutineScope
under the hood, and every dispatcher is aTestCoroutineDispatcher
. This means your tests can have granular control over every dispatcher without modifying production code.
@Test
fun someTest() = runBlocking {
val scope = TestProvidedCoroutineScope()
scope.pauseDispatcher()
// returns a Deferred<Data> using the "IO" dispatcher
val dataDeferred = SomeClass(scope).getDataFromNetwork()
dataDeferred.isCompleted shouldBe false
scope.resumeDispatcher()
dataDeferred.isCompleted shouldBe true
scope.cleanupTestCoroutines()
}
Better Android Lifecycle Awareness
Dispatch integrates with the Android lifecycle in a way similar to what thelifecycle-ktx
library does, but with more extensibility. The resultant coroutineScopes all contain DispatcherProviders
for easy integration with Espresso's IdlingResource
system.
class MyFragment : Fragment() {
init {
// dispatchLifecycleScope is bound to the Fragment lifecycle
// withViewLifecycle creates a child scope each time the View is created
dispatchLifecycleScope.withViewLifecycle(this) {
myViewModel.dataFlow
.onEach { /* ... */ }
// starts and stops collection along with the view lifecycle
.launchOnStart()
}
}
}
Android Espresso
Dispatch will sync all coroutines with Espresso's IdlingRegistry
, ensuring that Espresso waits until work is done before performing assertions.
// Retrieve the DispatcherProvider from a dependency graph,
// so that the same one is used throughout the codebase.
val customDispatcherProvider = testAppComponent.customDispatcherProvider
// Automatically register and unregister Dispatch's IdlingResource
@get:Rule val idlingRule = IdlingDispatcherProviderRule {
IdlingDispatcherProvider(customDispatcherProvider)
}
@Test
fun testThings() = runBlocking { /* ... */ }