Testing a Spring Boot application with Kotest
Tags: kotest, kotlin, testing, spring
Published: 2019-07-11 03:49:44

TL;DR - How to use the SpringListener from [Kotest](https://github.com/Kotest/Kotest) to test Spring Boot applications, including some samples

# Hello Kotliners!

In this article we'll see how to test Spring Boot apps using the [Kotest Framework](https://github.com/Kotest/Kotest). We'll see some examples on how we test things using JUnit, and how to easily move to Kotest and enjoy it's features.

## 3 simple steps

1. Add Kotest's Spring Extension to your `build.gradle`
2. Transform your JUnit test into Kotest format (or create a new test from scratch)
3. Add the SpringListener to your class


## Add Kotest Spring Extension

On your `build.gradle` file we'll add the Spring 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 Spring Extension definition close to my Kotest definition

build.gradle
```
dependencies {
    // ... Your dependencies ... 

    // Kotest
    testImplementation("io.kotest:kotest-runner-junit5:{version}")
    testImplementation("ioio.kotest.extensions:kotest-extensions-spring:{version}")
   
}
```

[<img src="https://img.shields.io/maven-central/v/io.kotest.extensions/kotest-extensions-spring.svg?label=latest%20release"/>](https://search.maven.org/artifact/io.kotest.extensions/kotest-extensions-spring)

## Transform a JUnit test to a Kotest Spec

For this part we'll assume that we already have a component in our application:

```kotlin
@Component
class SimpleComponent {
    fun foo() = "Bar"
}
```

Yes yes, it's very simple and very dummy... But stay with me, we will go step by step!


We usually write a JUnit + Spring integrated test for this, validating that this bean works correctly.

[There](https://www.baeldung.com/spring-boot-testing).[are](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html).[many](https://spring.io/guides/gs/testing-web/).[guides](https://reflectoring.io/unit-testing-spring-boot/) that show us how to do it. Let's take this basic approach:

```kotlin
@RunWith(SpringRunner::class)
@SpringBootTest
class SimpleComponentTest  {

    @Autowired
    private lateinit var simpleComponent: SimpleComponent
    
    @Test
    fun fooShouldReturnBar(){
        Assert.assertEquals("Bar", simpleComponent.foo())
    }
}
```

## Transform that test in a Kotest Spec

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`.

Let's convert it exactly as is:

```kotlin
@RunWith(SpringRunner::class)
@SpringBootTest
class SimpleComponentTest : FunSpec() {
    
    @Autowired
    private lateinit var simpleComponent: SimpleComponent
    
    init {
        test("foo should return Bar") {
            simpleComponent.foo() shouldBe "Bar"
        }
    }
}
```

Aaaand our test crashes.

> kotlin.UninitializedPropertyAccessException: lateinit property simpleComponent has not been initialized

It's ok, it's ok! We need to tell Kotest that this is a Spring Test!

## Add the SpringListener to the class

To fix the above error, we need to add the `SpringListener` to our class' listeners:

```kotlin
@SpringBootTest
class SimpleComponentTest : FunSpec() {
    
    override fun listeners(): List<TestListener> {
        return listOf(SpringListener)
    }
    
    @Autowired
    private lateinit var simpleComponent: SimpleComponent
    
    init {
        test("foo should return Bar") {
            simpleComponent.foo() shouldBe "Bar"
        }
    }
}
```

Notice that we also removed the `@RunWith(SpringRunner::class)`, as we are not running with JUnit anymore.

#### And _voilà_, it works!

Of course this is a very modest example. What about all the other configurations? Profiles, context configuration, TestConfiguration?

*Don't worry!* they'll work the same way as we're used to in JUnit. Annotating the constructor and such.

For example, messing with profiles:

```kotlin
@SpringBootTest(classes = [Components::class])
@ActiveProfiles("test-profile")
class ActiveProfileSpringTest : FunSpec() {

    override fun listeners() = listOf(SpringListener)

    @Value("\${test-foo}")
    lateinit var testFoo: String

    init {
        test("Should load active profile properties correctly") {
            testFoo shouldBe "bar"
        }
    }

}
```
[test from Kotest test suite](https://github.com/kotest/kotest-extensions-spring/blob/master/src/test/kotlin/io/kotest/extensions/spring/ActiveProfileSpringTest.kt)

----

And this is all we have for today! Go ahead and test your Spring Apps with Kotest! More information on this extension can be found at [the docs](https://kotest.io/docs/extensions/spring.html)

Doubts? Suggestions? Leave us a comment!