在appComponent dagger 2中动态添加测试模块?

时间:2018-05-29 09:04:46

标签: android unit-testing automated-tests android-espresso dagger-2

您可以在我的AppComponent中添加测试模块吗?

以下是我对appComponent

的真实再现
@Singleton
@Component(modules = arrayOf(MainModule::class,
        AnalyticsModule::class,
        MainAndroidBinding::class,
        AccountAndroidBinding::class,
        AndroidSupportInjectionModule::class,
        HomeAndroidBinding::class,
        NetworkModule::class))
interface ApplicationComponent : AndroidInjector<DaggerApplication> {
    fun inject(myApplication: MyApplication)
    override fun inject(instance: DaggerApplication)

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(applicaton: Application): Builder
        fun build(): ApplicationComponent
    }

}

我可以直接将测试模块添加到testAppComponent,但它不能为我提供动态添加不同testModule的灵活性。

@Singleton
@Component(modules = [
    (MainModuleTest::class),
    (TestMainAndroidBindingTest::class),
    (AccountAndroidBindingTest::class),
    (AnalyticsModuleTest::class),
    (AndroidSupportInjectionModule::class),
    (NetworkModuleTest::class)])
interface TestAppComponent : ApplicationComponent {

    fun inject(launchActivityTest: LaunchActivityTest)

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(applicaton: Application): Builder

        fun build(): TestAppComponent
    }
}

这是我的MyApplication类

class MyApplication : DaggerApplication() {

    companion object {

        private lateinit var application: MyApplication

        fun get(): MyApplication {
            return application
        }
    }


    @Inject
    lateinit var dispatchingActivityInjector: DispatchingAndroidInjector<Activity>

    lateinit var applicationComponent: ApplicationComponent

    override fun onCreate() {
        super.onCreate()
        application = this
    }

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
        applicationComponent = DaggerApplicationComponent.builder()
                .application(this)
                .build()
        applicationComponent.inject(this)
        return applicationComponent
    }

    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }

}

在LaunchActivityTest上,我将其设置为使用此testApp组件

  @Before
    fun setUp() {
        val app = InstrumentationRegistry.getTargetContext().applicationContext as MyApplication
        val testAppComponent = DaggerTestAppComponent.builder().application(app).build()
        app.applicationComponent = testAppComponent
        testAppComponent.inject(this)
    }

我正在遵循这个指南直到我偶然发现我的DaggerTestAppComponent没有公开模块让我动态添加自己,因为我的AppComponent类扩展了AndroidInjector,它会自动为你添加模块

https://proandroiddev.com/writing-espresso-instrumentation-tests-with-dagger2-kotlin-d30f12c4769b

以上动态添加其模块如下:

testAppComponent = DaggerTestAppComponent.builder()
                .appModule(AppModule(app))
                .apiModule(TestApiModule())
                .prefModule(TestPrefModule())
                .build()

我不能这样做,除非我重做我的AppComponent,以便它不会扩展AndroidInjector。如果我这样做,那么在我真正的impl代码中,我必须手动设置模块。

还有其他办法吗?

1 个答案:

答案 0 :(得分:1)

您应该向组件构建器添加一个函数,并使用“ BindsInstance”。

示例组件

@Singleton
@Component(modules = {
    AndroidSupportInjectionModule.class,
    ApplicationTestModule.class,
    ActivityBuilder.class})
public interface TestExampleComponent extends AndroidInjector<DaggerApplication> {

void inject(TestApplication app);

@Override
void inject(DaggerApplication instance);

@Component.Builder
interface Builder {
    @BindsInstance
    TestExampleComponent.Builder application(DaggerApplication application);
    Builder applicationModule(ApplicationTestModule appTestModule);
    TestExampleComponent build();
  }
}

在此组件中,我使用“ BindsInstance”添加了applicationModule函数,并且可以传递ApplicationTestModule。

然后您可以添加不同的测试模块。

TestApplicationComponent appComponent = DaggerTestAppComponent.builder().application(this).
applicationModule(appTestModule).build();
appComponent.inject(this);