huf*_*man 7 android unit-testing mvvm
我很高兴使用新的 Android 架构组件 ViewModel 系统,它很好地将 Activity/Fragment/Layout 渲染问题与 ViewModel 逻辑分开。我已经成功地对 ViewModel 进行了单独的单元测试,现在想通过向 Activity/Fragment 提供针对各种状态场景的模拟 ViewModel 来尝试一些屏幕截图测试。
我已经成功配置了我的 androidTests,以便能够在我的设备测试中使用 Mockito,这部分效果很好。
然而,官方推荐的调用 ViewModelProvider 或委托的方法by viewModels<>似乎没有提供注入模拟 ViewModel 的方法。我不想只是为了解决文档中的这一遗漏而添加整个 DI 框架,所以我想知道是否有人有任何成功的示例,可以使用官方 Android 架构组件提供模拟 ViewModel,而无需额外依赖 Dagger 或 Hilt。
一年前唯一相关的答案ActivityTestRule建议使用并手动控制活动生命周期,但该规则已被弃用,取而代之的activityScenarioRule是不提供此控制的规则。
我决定重写by viewModels委托来检查模拟 ViewModel 映射中的实例,因此我的活动可以使用正常的委托模式,并在未找到 ViewModel 时提供自己的工厂。
val mockedViewModels = HashMap<Class<*>, ViewModel>()
@MainThread
inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
noinline factoryProducer: (() -> ViewModelProvider.Factory)? = null
): Lazy<VM> {
// the production producer
val factoryPromise = factoryProducer ?: {
defaultViewModelProviderFactory
}
return createMockedViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
}
/// ... and similar for the fragment-ktx delegates
/**
* Wraps the default factoryPromise with one that looks in the mockedViewModels map
*/
fun <VM : ViewModel> createMockedViewModelLazy(
viewModelClass: KClass<VM>,
storeProducer: () -> ViewModelStore,
factoryPromise: () -> ViewModelProvider.Factory
): Lazy<VM> {
// the mock producer
val mockedFactoryPromise: () -> ViewModelProvider.Factory = {
// if there are any mocked ViewModels, return a Factory that fetches them
if (mockedViewModels.isNotEmpty()) {
object: ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return mockedViewModels[modelClass] as T
?: factoryPromise().create(modelClass) // return the normal one if no mock found
}
}
} else {
// if no mocks, call the normal factoryPromise directly
factoryPromise()
}
}
return ViewModelLazy(viewModelClass, storeProducer, mockedFactoryPromise)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3103 次 |
| 最近记录: |