We have an Android app that is using compose for the view layer and we are using Kodein for all of our dependency injections.
I have a BaseApplication class which is DIAware:
class BaseApplication : Application(), DIAware {
override val di: DI = DI.lazy {
import(modules) // modules defined in respective packages
}
}
I also have a MainActivity and a nav graph to manage navigation between the various composables.
Problem: How can I properly override these modules in my instrumented tests for MainActivity?
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()
val moduleOverrides = DI.Module(allowSilentOverride = true) {
// add bindings for fakes w/ allowOverride = true
}
@Before
fun setup() {
val application =
ApplicationProvider.getApplicationContext() as BaseApplication
// how can I override the BaseApplication modules for my test?
}
}
I cant seem to find any clear language on the matter and feel like I am missing something very obvious. Any help would be very much appreciated.
There are several ways to achieve that. The general approach is to override the actual modules like
val someParrentKodeinModule...
val mockModule = Kodein {
extend(someParrentKodeinModule, allowOverride = true)
bind<Foo>(overrides = true) with provider { Foo2() }
}
or
val kodein = Kodein {
/* ... */
import(testsModule, allowOverride = true)
}
where testsModule
is some module that already defines all the needed mock components that will be overridden in the main one.
Your approach is also good. The key point is to replace your DI with the needed one - this can be done making the DI in your app - var
instead of val
and assigning new value to it. But you will have to drop DIAware
class BaseApplication : Application() {
var di: DI = DI.lazy {
import(modules) // modules defined in respective packages
}
}
@Before
fun setup() {
val application =
ApplicationProvider.getApplicationContext() as BaseApplication
application.di = moduleOverrides
}
Something like that.
And generally using single DI for the app inside the App class is not recommended. Use specialized modules for each component of the app you want to test