Hi all :android-wave: , How to write integration t...
# koin
a
Hi all 👋 , How to write integration tests for application using Koin? I am getting the following error when running my tests.
Copy code
java.lang.IllegalStateException: KoinApplication has not been started
solved 1
UI Test code
Copy code
class HomeScreenTest {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Test
    fun homeScreenIsDisplayed() {
        composeTestRule.onNodeWithText("Home").assertIsDisplayed()
    }
}
Application class
Copy code
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            modules(
                MyAppModule().module,
            )
        }
    }
}
MainActivity
Copy code
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            HomeScreen()
        }
    }
}
Tried adding
startKoin
directly in the test setup. It didn't work.
Copy code
@Before
fun setUp() {
  startKoin {
    modules(MyAppModule().module)
  }
}
👍 1
Update: Issue Resolved. Complete Setup
InstrumentationTestRunner
Copy code
class InstrumentationTestRunner : AndroidJUnitRunner() {
    override fun newApplication(
        classLoader: ClassLoader?,
        className: String?,
        context: Context?
    ): Application {
        return super.newApplication(
            classLoader,
            TestApplication::class.java.name,
            context
        )
    }
}
KoinTestRule
Copy code
class KoinTestRule(
    private val modules: List<Module>,
) : TestRule {
    override fun apply(
        base: Statement,
        description: Description,
    ): Statement {
        return object : Statement() {
            override fun evaluate() {
                try {
                    stopKoin()
                    startKoin {
                        androidContext(
                            androidContext = InstrumentationRegistry.getInstrumentation().targetContext,
                        )
                        modules(
                            modules = modules,
                        )
                    }
                    base.evaluate()
                } finally {
                    stopKoin()
                }
            }
        }
    }
}
TestApplication
Copy code
class TestApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidLogger(
                level = Level.ERROR
            )
            androidContext(
                androidContext = this@TestApplication,
            )
            modules(
                modules = testApplicationModule,
            )
        }
    }
}
TestApplicationModule
Copy code
val testApplicationModule = module { 
  // Add instrumented common test dependencies here
}
TestModule
Copy code
internal val androidTestModule = module {
    // Add instrumented test-specific dependencies here
}
HomeScreenTest
Copy code
@RunWith(AndroidJUnit4::class)
internal class HomeScreenTest {
    @get:Rule(order = 0)
    val koinTestRule = KoinTestRule(
        modules = listOf(
            MyAppModule().module,
            androidTestModule,
        ),
    )

    @get:Rule(order = 1)
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Before
    fun setup() {
        // Setup will be added if needed
    }

    @Test
    fun homeScreen_isDisplayed() {
        composeTestRule.onNodeWithText("Home").assertIsDisplayed()
    }
}