I am currently working my way through this article, trying to mock dagger dependencies in android with Kotlin but am having some trouble.
I am receiving an error saying activityInjector is not initialised.
What am I doing wrong?
TestAppComponent
@Singleton
@Component(
modules = [
AndroidSupportInjectionModule::class,
TestAppModule::class,
ActivityModule::class,
FragmentModule::class,
ViewModelModule::class
]
)
interface TestAppComponent : AndroidInjector<TestApp> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<TestApp>() {
abstract fun appModule(appModule: TestAppModule): Builder
}
}
TestApp
class TestApp: Application(), HasActivityInjector {
@Inject
lateinit var activityInjector: DispatchingAndroidInjector<Activity>
override fun activityInjector(): AndroidInjector<Activity> = activityInjector
}
Test Injector
class TestInjector(private val testAppModule: TestAppModule) {
fun inject() {
val testApp= ApplicationProvider.getApplicationContext() as TestApp
DaggerTestAppComponent
.builder()
.appModule(testAppModule)
.create(testApp)
.inject(testApp)
}
}
Activity Module
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun provideNavigationActivity(): NavigationActivity
}
Instrumented Unit Test
@Rule
@JvmField
var navigationActivityTestRule = ActivityTestRule(NavigationActivity::class.java, true, true)
@MockK
private lateinit var repo: Repo
@Before
fun setUp() {
MockKAnnotations.init(this)
TestInjector(TestAppModule(repo)).inject()
}
Because of the ActivityTestRule
your activity is launched even before the TestInjector
is called from your setup method. You need to defer activity launch until your DaggerTestAppComponent
is built.
Try this:
@Rule
@JvmField
var navigationActivityTestRule = ActivityTestRule(NavigationActivity::class.java, true, false)
// ^^ Notice the third parameter here, passing false will not launch the activity
@MockK
private lateinit var repo: Repo
@Before
fun setUp() {
MockKAnnotations.init(this)
TestInjector(TestAppModule(repo)).inject()
// Launch the activity now that TestInjector is called
navigationActivityTestRule.launchActivity(Intent())
}