You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:11:28