Search code examples
androiddependency-injectionkotlindagger-2dagger

How to inject mocks with Dagger 2.11


I am trying to inject mocks using the Android Injector of Dagger 2.11.

Before using the Android Inject I used to change the injector in the Application class so I can inject mocks. Like this:

class EGOApplication : Application() {

    lateinit var injectorComponent: InjectorComponent


    override fun onCreate() {
        super.onCreate()

        injectorComponent = DaggerInjectorComponent.builder()
                .appModule(AppModule(this))               
                .build()
}

And in my tests I used to change the injectorComponent like this:

app.injectorComponent = DaggerMockComponent.builder()
                .mockModule(MockModule(app))
                .build()

And then I can inject my mocks from MockModule.

But now I am using Android Injector form this tutorial: https://medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe

Well... now I inject my dependencies like this:

override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
}

So my approach doesn't work anymore... How can I make Dagger injector dependencies from my MockModule?

Any help is appreciated!


Solution

  • I found a answer.

    I were changing the injectorComponent in my tests... Like this:

    @Inject
    lateinit var someDependency: SomeDependency
    
    val app = instrumentation.targetContext.applicationContext as MyApplication
    
    app.injectorComponent = DaggerMockComponent.builder()
                    .mockModule(MockModule(app))
                    .build()
    
    if (null == mockComponent) {
          mockComponent = app.injectorComponent as MockComponent
          mockComponent!!.inject(this)
    }
    

    My application were, more or less, like this:

    open class MyApplication : Application(), HasActivityInjector {
            @Inject
            lateinit var androidInjector : DispatchingAndroidInjector<Activity>
    
        lateinit var injectorComponent: InjectorComponent
    
        override fun onCreate() {
            super.onCreate()              
    
            buildInjector()
    
        }
    
    
        open fun buildInjector() {
            injectorComponent = DaggerInjectorComponent.builder()
                    .dataModule(DataModule())
                    .appModule(AppModule(this))
                    .trackerModule(TrackerModule(this, FirebaseAnalytics.getInstance(this)))
                    .build()
        }
    
        override fun activityInjector(): AndroidInjector<Activity> = androidInjector
    
    }
    

    But now I am using a different Application for my tests where I extend the default Application (a TestApplication). In this application I construct a different injector:

    class TestApplication : MyApplication() {
    
        override fun buildInjector() {
            injectorComponent = DaggerMockComponent.builder().mockModule(MockModule(this)).build()
        }
    }
    

    You will need create a MockComponent that extends the InjectorComponent and a MockModule that provides all the mocks that you need.

    Then in your test just do:

    @Before
    fun setUp() {
        val app = instrumentation.targetContext.applicationContext as TestApplication
        (app.injectorComponent as MockComponent).inject(this)
    }
    

    It works just fine!