TL;DR - Using the KoinListener
from Kotest to write tests that depend on Koin modules in a Kotest Spec
Hello, Kotliners!
In this article we will see how to test applications that use the Koin DI Framework in a Spec
from the Kotest Framework. We'll take the JUnit example from Koin's documentation and enhance it with Kotest.
3 simple steps
- Add Kotest's Koin extensions to your build.gradle
- Transform your JUnit test into a Kotest Spec (or create one from scratch)
- Add the KoinListener to your class
Add Koin extension to your build.gradle
On your build.gradle
file we'll add the Koin Extension dependency as a testImplementation
. I'm assuming you already have Kotest configured. If you don't, take a look at the docs on how to do it.
I like to keep the Koin Extension definition close to my Kotest definition
build.gradle
dependencies {
// ... Your dependencies ...
// Kotest
testImplementation("io.kotest:kotest-runner-junit5:{version}")
testImplementation("io.kotest:kotest-extensions-koin:{version}")
}
Transform a JUnit test to a Kotest Spec
For this example, we are going to use the JUnit example from the Koin docs:
class MyTest : KoinTest {
// Lazy inject property
val componentA : ComponentA by inject()
// use it in your tests :)
@Test
fun `make a test with Koin`() {
startKoin { modules(appModule) }
// use componentA here!
}
}
Converting the test
There are a lot of styles that can be used in Kotest, let's try with FunSpec
class MyTest : FunSpec(), KoinTest {
// Lazy inject property
val componentA : ComponentA by inject()
init {
test("Make a test with Koin") {
startKoin { modules(appModule) }
// use componentA here!
}
}
}
This will already work!
This example works in the same way as the JUnit code. If we add more tests to the class, we'll have to clear Koin's context. In JUnit we create a @After
method. Let's see how to do this in Kotest
Add KoinListener to the class
To fix this, we can either override the afterTest
function, that works similarly to @After
or we can use the KoinListener
to do that automatically for us! Let's try with that approach:
class MyTest : FunSpec(), KoinTest {
override fun listeners() = listOf(KoinListener(appModule))
// Lazy inject property
val componentA : ComponentA by inject()
init {
test("Make a test with Koin") {
// use componentA here!
}
}
}
With KoinListener
we will have Kotest handle both Koin's start (see that we removed that line in our test!) and Koin's stop.
And that's it!
With this simple setup, you'll be able to test your Koin Application with Kotest, and use all the available features from both of them!
If you still have any doubt, check out the full documentation on KoinListener
Top comments (1)
Hi , am new to testing and i work on android app and using koin for di ,
Should i use koinTest to inject my classes instead of mocking them to test behavior