Last active
April 18, 2018 06:59
-
-
Save tomkoptel/1101b2bb61f3daf251e3d627ee533b92 to your computer and use it in GitHub Desktop.
JUnit 4 TestRule that replaces CoroutinesProvider implementation with Espresso aware one.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.support.test.espresso.IdlingRegistry | |
import android.support.test.espresso.IdlingResource | |
import kotlinx.coroutines.experimental.CoroutineScope | |
import kotlinx.coroutines.experimental.CoroutineStart | |
import kotlinx.coroutines.experimental.Job | |
import org.junit.rules.TestRule | |
import org.junit.runner.Description | |
import org.junit.runners.model.Statement | |
import kotlin.coroutines.experimental.CoroutineContext | |
// We use Kotlin alias to not confuse original high-order function with our delegate | |
import kotlinx.coroutines.experimental.launch as coroutineLaunch | |
// https://gist.github.com/tomkoptel/6563da1e3c7426d36596ed84e354f5d7 | |
import com.sample.utils.CoroutinesProvider | |
/** | |
* Following [TestRule] ensures that Espresso waits for the underlying coroutines to finish their execution. We | |
* perform the fit by overriding Singleton component that serves as simplified DI implementation in the project. | |
*/ | |
class CoroutinesIdlingResourceRule : TestRule { | |
private val resources = mutableListOf<IdlingResource>() | |
private val idlingRegistry = IdlingRegistry.getInstance() | |
override fun apply(base: Statement, description: Description): Statement { | |
return object : Statement() { | |
override fun evaluate() { | |
overrideDefaultCoroutinesProvider() | |
base.evaluate() | |
resources.forEach { idlingRegistry.unregister(it) } | |
} | |
} | |
} | |
private fun overrideDefaultCoroutinesProvider() { | |
// This is a dummy way to override the dependency. I have used custom Application class to cache global singleton component | |
// that is used as an access point to replace dependency with custom implementation. | |
AppUnderTest.component().coroutinesProvider = object : CoroutinesProvider { | |
override fun launch( | |
context: CoroutineContext, | |
start: CoroutineStart, | |
parent: Job?, | |
block: suspend CoroutineScope.() -> Unit | |
): Job { | |
// Use original couroutoine factory function. 'coroutineLaunch' is an alias of original `launch` | |
val job = coroutineLaunch(context, start, parent, block) | |
// Tranform job to IdlingResource and register in the Espresso | |
job.asIdlingResource().let { | |
idlingRegistry.register(it) | |
resources.add(it) | |
} | |
return job | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment