从所有模块访问通用协程规则 - Android 单元测试
我有一个 TestWatcher
类实现 TestCoroutineScope
接口,如下所示:
@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()
}
}
这用于使用 kotlin 协程向 ViewModelTest
提供 Loopers,例如:
@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")
}
}
我的问题是我只能从 BlaViewModelTest
所在的同一模块测试目录访问 MainCoroutineRule
。
如果我将 MainCoroutineRule
移动到公共模块中的测试目录,假设 base
,BlaViewModelTest
无法在期间访问 MainCoroutineRule
测试运行时间最终失败。编译时没有问题。
我尝试将 MainCoroutineRule
移动到 base
的主包中,但它迫使我在项目中实现测试库,从我的角度来看,这不是一个好方法。
我不想为所有模块重复 MainCoroutineRule
,我想从公共源访问它。
任何方法将不胜感激。
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 ViewModelTest
s 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
测试源在消费者模块中不可用。我不知道为什么它们在编译时可用以及为什么 IDE 不会抱怨它,但我确实经历过同样的事情。
为了解决这个问题,您可以创建一个单独的仅测试模块(例如
base-testing
、test-utils
)。该规则应该是模块正常源的一部分(src/main
,不是src/test
)。然后,您可以将该模块作为testImplementation
包含在您的使用者模块中。Test sources won't be available in consumer modules. I 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
, notsrc/test
). Then you can include that module astestImplementation
in your consumer modules.