I found two ways to solve the problem:
I consider the first approach cleaner and would recommend to use it rather than the latter, but I'll describe both of them, so you can make your own choice.
Build flavors with typealias
- Create two product flavors,
mock
and prod
:
app/build.gradle
android {
...
productFlavors {
prod
mock {
applicationIdSuffix '.mock'
}
}
}
- Then set the
typealias
depending on the flavor, let's call it BaseFragment
:
prod
flavor,
app/src/prod/com.example.mypackage/BaseFragment.kt
typealias BaseFragment = DaggerFragment
mock
flavor, app/src/mock/com.example.mypackage/BaseFragment.kt
typealias BaseFragment = Fragment
- And finally use the
BaseFragment
alias in your fragments:
class SomeFragment : BaseFragment() {
...
}
- To test the code using
FragmentScenario
switch from the prod*
build variant to the mock*
one and set all the dependencies that are supposed to be injected somewhere in your test class (e.g. using mocks)
Own DaggerFragment
and test variants of the fragments
- Create your own
DaggerFragment
(based on the actual dagger.android.support.DaggerFragment
implementation):
abstract class DaggerFragment() : Fragment(), HasAndroidInjector {
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Object>
override fun onAttach(context: Context) {
injectMembers()
super.onAttach(context)
override fun androidInjector(): AndroidInjector<Object> = androidInjector
protected open fun injectMembers() = AndroidSupportInjection.inject(this)
}
- Extend your
DaggerFragment
implementation and set the fragment open
:
open class SomeFragment : DaggerFragment() {
...
}
- Create another implementation of your fragment for the test purposes and override the
injectMembers
method:
class TestSomeFragment : SomeFragment() {
override injectMembers() {
/* you can manually inject dependencies and mocks here */
}
}
- Use
TestSomeFragment
in your tests.