从所有模块访问通用协程规则 - Android 单元测试

发布于 2025-01-14 03:25:44 字数 2030 浏览 4 评论 0原文

我有一个 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 移动到公共模块中的测试目录,假设 baseBlaViewModelTest 无法在期间访问 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 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

剧终人散尽 2025-01-21 03:25:44

如果我将 MainCoroutineRule 移动到公共模块中的测试目录,假设 baseBlaViewModelTest 无法访问 MainCoroutineRule code> 在测试运行期间最终失败。编译时没有问题。

测试源在消费者模块中不可用。我不知道为什么它们在编译时可用以及为什么 IDE 不会抱怨它,但我确实经历过同样的事情。

为了解决这个问题,您可以创建一个单独的仅测试模块(例如base-testingtest-utils)。该规则应该是模块正常源的一部分(src/main不是 src/test)。然后,您可以将该模块作为 testImplementation 包含在您的使用者模块中。

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.

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, not src/test). Then you can include that module as testImplementation in your consumer modules.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文