【问题标题】:Testing android fragments with activityViewModels使用 activityViewModels 测试 android 片段
【发布时间】:2021-07-01 20:10:11
【问题描述】:

我正在尝试为共享相同 ViewModel 的片段运行 android 仪器测试。 ViewModel 有一些参数。 我使用 koin,但是在测试中使用 activityViewModels 时,koin 不会注入 ViewModel。

class SomeFragment() : Fragment() {
    private val viewModel: SomeViewModel by activityViewModels()
    ... more code
}

class SomeFragmentTest() : KoinTest{

    @Before
    fun setup() {
        val viewModel: SomeViewModel = mockk(relaxed = true)

        startKoin { loadKoinModules(listOf(
            module(override = true) { viewModel },
            module(override = true) { factory { appAnalytics } })) }
    }
.... more code
}

收到的消息是

Caused by: java.lang.InstantiationException: java.lang.Class<SomeViewModel> has no zero argument constructor

【问题讨论】:

  • 您应该标记自己的答案 :) 这是一个很好的解决方案,在 2021 年 11 月仍然有效。

标签: android unit-testing testing


【解决方案1】:

我找到了解决方案,并发布了这个问题,希望对其他人有所帮助。

我在片段中添加了一个视图模型工厂:

class SomeFragment(val factory: (() -> ViewModelProvider.Factory)? = null) : Fragment() {
    private val viewModel: SomeViewModel by activityViewModels(factory)
    ... more code
}

class SomeFragmentTest() : KoinTest{
    private val fragmentFactory : FragmentFactory = mockk() 
    
    @Before
    fun setup() {
        val viewModel: SomeViewModel = mockk(relaxed = true)
        ... some mock related to viewModel
        val viewModelFactory : ViewModelProvider.Factory = mockk()
        every { viewModelFactory.create(SomeViewModel::class.java) } answers { viewModel }
        every { fragmentFactory.instantiate(any(), any()) } answers { SomeFragment{
            viewModelFactory
        }}
    }
    @Test
    fun test_fragment() {
        launchFragmentInContainer<SomeFragment>(
            themeResId = R.style.AppTheme,
            factory = fragmentFactory
        )
        ... some asserts 
    }

.... more code
}

这适用于 prod,因为在工厂为 null 时的 activityViewModels 实现中使用默认值:

inline fun <reified VM : ViewModel> Fragment.activityViewModels(
    noinline factoryProducer: (() -> Factory)? = null
) = createViewModelLazy(VM::class, { requireActivity().viewModelStore },
    factoryProducer ?: { requireActivity().defaultViewModelProviderFactory })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多