Kotest Spring Extension(SpringExtension)
Spring Extension
Adding the Dependency
To use this extension, add the io.kotest.extensions:kotest-extensions-spring module to the test compile path. You can check the latest version on Maven Central.
First, to use Kotest with Spring, add the following dependency.
testImplementation("io.kotest.extensions:kotest-extensions-spring:1.0.0")
Note: The Maven group ID differs from the core test framework group,
io.kotest.extensions.
Configuration
To apply SpringExtension to all tests, configure it through global settings.
class GlobalProjectConfig : AbstractProjectConfig() {
override fun extensions() = listOf(SpringExtension)
}
To use the Spring extension, it must be enabled for all test classes or per test class.
To enable it globally, register SpringExtension in the project configuration:
class ProjectConfig : AbstractProjectConfig() {
override fun extensions() = listOf(SpringExtension)
}
Sometimes you may want to use tests without enabling SpringExtension globally. In this case, you can skip global configuration and configure extensions only in the test classes that use SpringExtension.
To enable it per test class:
class SpringTest : FunSpec() {
override fun extensions() = listOf(SpringExtension)
}
To tell Spring which configuration class to use, add the @ContextConfiguration annotation to the Spec class. This annotation should point to a class annotated with Spring’s @Configuration annotation. Alternatively, you can use @ActiveProfiles to point to a specific application context file.
Constructor Injection
For constructor injection, assuming autoscan is enabled, Kotest automatically registers SpringAutowireConstructorExtension when the Spring module is added to the build. If autoscan is disabled, you must manually load the extension in project configuration.
This extension intercepts each call that creates a Spec instance and autowires beans declared in the primary constructor.
The following example is a test class that requires a service named UserService in its primary constructor. This service class is a normal Spring bean annotated with @Component.
@ContextConfiguration(classes = [(Components::class)])
class SpringAutowiredConstructorTest(service: UserService) : WordSpec() {
init {
"SpringExtension" should {
"have autowired the service" {
service.repository.findUser().name shouldBe "system_user"
}
}
}
}
You can also use @SpringBootTest:
@SpringBootTest(classes = [FooService::class])
class SpringTest(fooService: FooService) : FunSpec() {
override fun extensions() = listOf(SpringExtension)
init {
test("getFoo test") {
val actual = fooService.getFoo()
actual shouldBe Foo("id", "foo")
}
}
}
@Service
class FooService {
fun getFoo(): Foo {
return Foo("id", "foo")
}
}
data class Foo(
val id: String,
val title: String,
)
Test Context
The Spring extension makes TestContextManager available through the coroutine context where the test runs. You can get a handle to this instance through the testContextManager() extension method.
This lets you obtain the test context that Spring is using.
class MySpec(service: UserService) : WordSpec() {
init {
"SpringExtension" should {
"provide the test context manager" {
println("The context is " + testContextManager().testContext)
}
}
}
}
Test Method Callbacks
Spring has various test callbacks such as beforeTestMethod, based on the idea that tests are methods. This assumption fits legacy test frameworks such as JUnit, but not modern test frameworks like Kotest, where tests are functions.
Therefore, when using nested spec styles, you can customize when test method callbacks are executed. By default, this is at the leaf node. You can pass a SpringTestLifecycleMode argument to the extension to run them at the root node:
class ProjectConfig : AbstractProjectConfig() {
override fun extensions() = listOf(SpringTestExtension(SpringTestLifecycleMode.Root))
}
Final Classes
When using final classes, you may receive the following warning from Kotest:
Using SpringListener on a final class. If any Spring annotation fails to work, try making this class open
If desired, you can disable this warning by setting the system property kotest.listener.spring.ignore.warning to true.