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???
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