Android插桩测试中如何为Fragment注入ViewModel工厂?
解决插桩测试中Fragment的Dagger依赖注入问题
问题背景
现有正常运行的Dagger AppComponent,为插桩测试创建了TestComponent,替换了ApiModule和DatabaseModule为模拟/测试实现。但使用launchFragmentInContainer启动MovieListingFragment时,Fragment无法注入ViewModelProvider.Factory,导致依赖未初始化。
解决方案
1. 创建测试专用Application,替换Dagger组件
测试环境需要用TestComponent替代原有的AppComponent,因此创建TestApp继承自你的App类,在onCreate中初始化TestComponent:
class TestApp : App() { override fun onCreate() { super.onCreate() DaggerTestComponent.builder() .application(this) .build() .inject(this) } }
2. 调整TestComponent的Builder,支持绑定Application
原TestComponent的Builder缺少@BindsInstance绑定Application的逻辑,需要补充(和AppComponent保持一致),否则无法完成Application级别的依赖注入:
@Singleton @Component( modules = [ MockApiModule::class, TestDatabaseModule::class, ViewModelModule::class, ActivityModule::class, AndroidSupportInjectionModule::class ] ) interface TestComponent : AndroidInjector<App> { @Component.Builder interface Builder { @BindsInstance fun application(app: Application): Builder fun build(): TestComponent } }
3. 配置测试目录的AndroidManifest.xml
在src/androidTest/AndroidManifest.xml中指定测试时使用TestApp,确保测试进程启动时加载的是测试专用Application:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.your.package"> <!-- 替换为你的应用包名 --> <application android:name=".TestApp" android:allowBackup="false" android:label="Test App"> </application> </manifest>
4. 确保BaseFragment的注入逻辑正确
你的BaseFragment需要在onAttach阶段触发Dagger注入,确保Fragment能获取到Component提供的依赖:
abstract class BaseFragment : Fragment() { override fun onAttach(context: Context) { AndroidInjection.inject(this) super.onAttach(context) } }
5. 测试代码无需额外修改
完成上述配置后,原测试代码即可正常运行,MovieListingFragment会通过TestComponent注入ViewModelProvider.Factory:
@RunWith(AndroidJUnit4::class) class MovieListFragmentTest { @Test fun testMovieListFragment() { val scenario = launchFragmentInContainer<MovieListingFragment>() scenario.moveToState(Lifecycle.State.RESUMED) // 后续可添加断言逻辑 } }
内容的提问来源于stack exchange,提问作者Samuel Robert
相关产品推荐
相关产品推荐

