You need to enable JavaScript to run this app. Android开发中如何Mock Hilt注入的ViewModel(Assisted Factory为final无法匿名继承)
优惠活动
大模型
产品
解决方案
定价
更多

Android开发中如何Mock Hilt注入的ViewModel(Assisted Factory为final无法匿名继承)

Hilt 注入 Assisted ViewModel 的 Mock 方案

问题根因

编译报错本质是测试思路的偏差:

  • Hilt 为带 Assisted 注入的 ViewModel 生成的MyViewModel_AssistedFactory是编译期自动生成的final类,设计上就不允许被继承扩展
  • 试图匿名实现这个final类的操作完全没有必要:生产模块里@Binds绑定的实际暴露类型是ViewModelAssistedFactory<out ViewModel>,那个生成的工厂只是这个接口的生产侧实现而已,测试阶段完全可以绕开这个实现类,直接替换接口的提供逻辑,从根源上避开final类继承的限制。

具体实现步骤

  • 第一步:定义测试专属的替代模块
    不需要手动写匿名类继承生成的工厂,直接在测试模块里提供自定义的ViewModelAssistedFactory实现,把你Mock的ViewModel实例包装进去即可。如果是Hilt 2.38以上版本,可以直接用@TestInstallIn注解定义测试模块,避免代码污染生产构建:
    @TestInstallIn(
        components = [ActivityRetainedComponent::class],
        replaces = ActivityModule::class
    )
    @Module
    object TestActivityModule {
        @Provides
        @IntoMap
        @StringKey("my.package.MyViewModel")
        fun provideMockMyViewModelFactory(): ViewModelAssistedFactory<out ViewModel> {
            // 直接实现工厂接口,返回Mock的ViewModel实例
            return ViewModelAssistedFactory {
                mock<MyViewModel>()
            }
        }
    }
    
  • 第二步:调整测试类代码
    把之前试图构造MyViewModel_AssistedFactory匿名实现的报错代码全部删除,Hilt会自动把测试模块提供的Mock工厂注入到对应的ViewModel Map中,Fragment运行时拿到的就是Mock出来的ViewModel实例:
    @HiltAndroidTest
    class FragmentTest {
        @get:Rule
        val hiltRule = HiltAndroidRule(this)
    
        // 可选:直接注入ViewModel工厂Map,方便手动控制Mock的行为
        @Inject
        lateinit var viewModelFactoryMap: Map<String, @JvmSuppressWildcards ViewModelAssistedFactory<out ViewModel>>
    
        @Before
        fun setup() {
            hiltRule.inject()
        }
    
        @Test
        fun testFragment正常渲染() {
            // 取出对应key的工厂,拿到Mock的ViewModel实例
            val mockViewModel = viewModelFactoryMap["my.package.MyViewModel"]?.create() as MyViewModel
            // 用Mockito配置Mock的返回值、校验交互逻辑
            `when`(mockViewModel.pageTitle).thenReturn("测试标题")
    
            // 后续启动Fragment,验证UI表现即可
        }
    }
    

兼容与注意事项

  • 如果使用的Hilt版本还不支持@TestInstallIn注解,可以把上述的TestActivityModule移动到androidTest源集下,使用普通的@InstallIn(ActivityRetainedComponent::class)注解,配合测试类上原有的@UninstallModules(ActivityModule::class)注解即可达到相同效果
  • 完全不需要为了Mock这个场景额外开启Mockito的final类Mock支持,那个生成的工厂类在测试流程中根本不会被加载
  • 替换绑定的时候一定要保证@StringKey的字符串和生产模块里的完全一致,否则会出现绑定失效,还是拿到真实的ViewModel实例
  • 如果你的ViewModel构造里有Assisted参数,直接在工厂的create()方法里返回对应参数的Mock对象即可,不需要走真实的参数解析流程

内容的提问来源于stack exchange,提问作者DeveloperKurt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.10 06:36:04