Search code examples
androidandroid-instrumentationkoin

Proper instrumentation test with Koin


Can't get this thing to work correctly.

  1. I have custom test application registered under test runner:
class HelloInstrumentationTestRunner : AndroidJUnitRunner() {
    override fun newApplication(
        cl: ClassLoader?, className: String?, context: Context?
    ): Application {
        return Instrumentation.newApplication(HelloTestApp::class.java, context)
    }
}
  1. My application instance starts koin like usual:
        startKoin {
            androidLogger()
            androidContext(applicationContext)
            fragmentFactory()
            modules(appModule + viewModelsModule)
        }
  1. Problem 1: In my instrumentation tests, I cannot do stopKoin() (says No Koin Context configured. Please use startKoin or koinApplication DSL)
  2. Problem 2: When I try to workaround the situation with unloadKoinModules/loadKoinModules in @After, my declareMockin subsequent test methods are no longer working.

All these problems are basically because application instance survives between tests, thus graph configured inside android application instance also survives between tests. I need that not to happen or at least have ability to modify graph between tests.


Solution

  • Solved.

    1. I had to setup override module:
        val overrideModule = module(override = true) {
            single<Repository1> {
                mock(Repository1::class.java)
            }
            single { Repository2(get(), get()) }
            single<Repository3> {
                mock(Repository3::class.java)
            }
            ...
        }
    
    1. In my @BeforeTest, I now do loadKoinModules(overrideModule)
    2. In my @AfterTest, I do unloadKoinModules(overrideModule)
    3. Inside my tests, I can now do:
            given(get<Repository1>().magicCall()).willReturn(
                MagicData(
                    "1111",
                    Calendar.getInstance().timeInMillis
                )
            )
    

    No need to deal with stopKoin and stuff like that, super easy!