Testing Koin applications with Kotest
Tags: kotlin, kotest, testing, koin
Published: 2019-07-22 15:09:16

TL;DR - Using the `KoinListener` from [Kotest](https://github.com/kotest/kotest) to write tests that depend on [Koin](https://insert-koin.io/) modules in a Kotest Spec


# Hello, Kotliners!

In this article we will see how to test applications that use the [Koin DI Framework](https://insert-koin.io/) in a `Spec` from the [Kotest](https://github.com/kotest/kotest) Framework. We'll take the JUnit example from Koin's documentation and enhance it with Kotest.


## 3 simple steps

1. Add Kotest's Koin extensions to your build.gradle
2. Transform your JUnit test into a Kotest Spec (or create one from scratch)
3. 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](https://github.com/kotest/kotest#use) 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](https://insert-koin.io/docs/2.0/quick-references/testing-your-components/):

```
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](https://github.com/Kotest/Kotest/blob/master/doc/styles.md) 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](https://github.com/Kotest/Kotest/blob/master/doc/extensions.md#koin) on `KoinListener`