DaggerMock
DaggerMock copied to clipboard
Mocking modules that depend on the activity
In my activity I have a module that depends on the activity itself. How would I mock this with DaggerMock?
I have tried instantiating it in the test like I would any other module, but unfortunately the activity is only available after the rules are run:
@get:Rule
private val intentsRule = IntentsTestRule(HomeActivity::class.java)
private val activity by lazy { intentsRule.activity!! }
@get:Rule
val daggerRule = DaggerMock.rule<HomeComponent>(HomeModule(), ActivityModule(activity)) {
set { activity.component = it }
}
would throw a nullptr exception. In this specific case I only need to mock objects that are in the HomeModule, so I guess I might be able to just pass in a mocked ActivityModule. But who knows if this will work and in the future I might have to use stuff inside the ActivityModule as well.
Usually you shouldn't pass the ActivityModule in the rule, however it depends on how you have organized your code. Here you can find an example when a presenter defined in an activity module is mocked (it works if you are using subcomponents).
How else would I be able to mock the presenter when it's in the HomeComponent/HomeModule, not the AppComponent?
I have tried just replacing the AppComponent like in the example you linked, but I'm getting runtime errors along the lines of "@Provides annotated method can not return null". Maybe it's because I'm not using subcomponents? My components generally look like this:
@PerActivity
@Component(
modules = arrayOf(HomeModule::class, ActivityModule::class),
dependencies = arrayOf(AppComponent::class))
interface HomeComponent : AppComponent {
fun exposePresenter(): HomeContract.Presenter
fun inject(activity: HomeActivity)
}
Unfortunately you can mock the presenter using DaggerMock only if you use subcomponents or if you define it in the main component. However it's hard to replace it with a mock even without DaggerMock.