0

I have been using Dagger Android for a while, and now I want to inject a MockModule for testing purposes, and I do not know how to get it. I have seen on some posts that they call something like:

DaggerAppComponent.builder()
  .dataModule(myMockModule)
  .create(this).inject(this)

But I have this configuration:

@Singleton
@Component(modules = [
    AndroidSupportInjectionModule::class,
    ActivitiesBuilderModule::class,
    AppModule::class,
    DataModule::class
])
internal interface AppComponent : AndroidInjector<CbvApplication> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<CbvApplication>()

}

and when I create the application, the DaggerAppComponent.Builder does not provides the setters for the individual modules. That is nice cause in the app code I do not have to worry about it, but on testing, I want to inject my mock objects through mockComponents / modules.

Anyone can point me in the right direction???

Chiara
  • 1,867
  • 15
  • 17

1 Answers1

1

As far as I know, I am not sure we can mock the whole module all together, but we can mock dependencies provided by module. I have achieved this like, I need to mock DataModule for UI Testing so I have created this TestDataModule and provided mocks for the dependency.

import com.nhaarman.mockito_kotlin.mock
import dagger.Module
import dagger.Provides
import javax.inject.Singleton

@Module
class TestDataModule {

    @Provides
    @Singleton
    fun providesDataRepository(): DataRepository {
        return mock()
    }
}

Here is TestApplicationModule

@Module
abstract class TestApplicationModule {

    @Binds
    abstract fun bindContext(application: Application): Context
}

And created TestApplicationComponent which will take the required modules

@Singleton
@Component(modules = [
    (AndroidSupportInjectionModule::class),
    (TestApplicationModule::class),
    (UIModule::class),
    (PresentationModule::class),
    (TestDataModule::class)])
interface TestApplicationComponent {

    // Here you can add additional direct mock 
    // classes to access them directly from component reference
    fun dataRepository(): DataRepository 


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

        fun build(): TestApplicationComponent
    }

    fun inject(app: TestAppplication)
}

I had to test UI using Android JUnit Test runner and espresso, So I used UIModule and Presentation Module as it is (Cannot mock as wanted to test). So have to mock other dependencies which are not part of that UI Unit tests like DataRepository

You can add other modules like CacheModule and RemoteModules as mocks as they don't play any role in UI Unit testing.

Finally, Create DaggerTestApplicationComponent in TestApplication like this,

class TestApplication : Application(), HasActivityInjector {

    @Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity>
    private lateinit var appComponent: TestApplicationComponent

    override fun onCreate() {
        super.onCreate()
        appComponent = DaggerTestApplicationComponent.builder()
                .application(this)
                .build()
        appComponent.inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity> = activityInjector
}

So now DaggerTestApplicationComponent will generate required dependency graph.

Note: It is required to stub all the methods called on mocked dependencies

adityakamble49
  • 1,971
  • 18
  • 27