TL;DR - How to use the SpringListener from 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. 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
- Add Kotest's Spring Extension to your
build.gradle
- Transform your JUnit test into Kotest format (or create a new test from scratch)
- 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 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}")
}
Transform a JUnit test to a Kotest Spec
For this part we'll assume that we already have a component in our application:
@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.are.many.guides that show us how to do it. Let's take this basic approach:
@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 that can be used in Kotest, let's try with FunSpec
.
Let's convert it exactly as is:
@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:
@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:
@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"
}
}
}
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
Doubts? Suggestions? Leave us a comment!
Top comments (4)
Nice post! Thank you 😁
Thank you very much, Pablo! I'm glad I could help
Thanks for the article! I've found it informative and useful.
Thanks, Karolis! Glad I could help