'Accessing Common Coroutine Rule From All Modules - Android Unit Test
I have a TestWatcher class implementing TestCoroutineScope interface as follows:
@ExperimentalCoroutinesApi
class MainCoroutineRule(private val dispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()) :
TestWatcher(),
TestCoroutineScope by TestCoroutineScope(dispatcher) {
override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(dispatcher)
}
override fun finished(description: Description?) {
super.finished(description)
cleanupTestCoroutines()
Dispatchers.resetMain()
}
}
This is used to provide Loopers to ViewModelTests using kotlin coroutines, for example:
@RunWith(JUnit4::class)
class BlaViewModelTest {
@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
@ExperimentalCoroutinesApi
@get:Rule
val coroutineRule = MainCoroutineRule()
@MockK
lateinit var blaUseCase: BlaUseCase
private lateinit var blaViewModel: BlaViewModel
@Before
fun setup() {
MockKAnnotations.init(this)
blaViewModel = BlaViewModel(blaUseCase)
}
@Test
fun testBla_Positive() {
coEvery {
blaUseCase.execute(any()).await()
} returns Resource.Success(Bla("data"))
blaViewModel.blaLiveData.observeForever {}
blaViewModel.bla()
assert(blaViewModel.blaLiveData.value != null)
assert(blaViewModel.blaLiveData.value is Resource.Success)
assert((blaViewModel.blaLiveData.value as? Resource.Success)?.value?.data == "data")
}
}
My problem is that I can only access MainCoroutineRule from the same module test directory where BlaViewModelTest remains.
If I move MainCoroutineRule to a test directory in a common module, let's say base, BlaViewModelTest cannot access MainCoroutineRule during test run time failing at the end. There is no problem in compile time.
I tried to move MainCoroutineRule into main package of base, but it forced me to implement test libraries in project which is not a good approach from my point of view.
I don't want to duplicate MainCoroutineRule for all modules, I want to access it from a common source.
Any approaches will be appreciated.
Solution 1:[1]
If I move
MainCoroutineRuleto a test directory in a common module, let's saybase,BlaViewModelTestcannot accessMainCoroutineRuleduring test run time failing at the end. There is no problem in compile time.
Test sources won't be available in consumer modules. I'm don't know why they're available at compile-time and why the IDE doesn't complain about it, but I definitely experienced the same thing.
To solve this you can create a separate test-only module (e.g. base-testing, test-utils). The rule should be part of the module's normal sources (src/main, not src/test). Then you can include that module as testImplementation in your consumer modules.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alex Krupa |
