I'm trying to run a simple unit test written with Kotest on a spring boot project. But unfortunately I get an error message
Testing started at 17:38 ...
Error: Unable to initialize main class io.kotest.launcher.LauncherKt
Caused by: java.lang.NoClassDefFoundError: io/kotest/core/engine/TestEngineListener
Process finished with exit code 1
My pom.xml file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-kotest-test</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>consoleApp</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<kotlin.code.style>official</kotlin.code.style>
<kotlin.compiler.jvmTarget>17</kotlin.compiler.jvmTarget>
<kotlin.version>1.7.10</kotlin.version>
</properties>
<repositories>
<repository>
<id>mavenCentral</id>
<url>https://repo1.maven.org/maven2/</url>
</repository>
</repositories>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>1.7.10</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>MainKt</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.7.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>io.kotest</groupId>
<artifactId>kotest-runner-junit5</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.kotest.extensions</groupId>
<artifactId>kotest-extensions-spring</artifactId>
<version>1.1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.kotest</groupId>
<artifactId>kotest-assertions-core-jvm</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Simple example of spring boot project
package org.example.spring.kotest.test
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.stereotype.Service
@SpringBootApplication
open class SpringKotestTestApplication
@Service
class SomeService {
fun foo() = 1
}
fun main(args: Array<String>) {
runApplication<SpringKotestTestApplication>(*args)
}
My unit test:
package org.example.spring.kotest.test
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.extensions.spring.SpringExtension
import io.kotest.matchers.shouldBe
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest
@EnableAutoConfiguration
class SomeServiceTest(
private val someService: SomeService
) : DescribeSpec() {
override fun extensions() = listOf(SpringExtension)
init {
describe("test") {
it("test") {
someService.foo().shouldBe(1)
}
}
}
}
I've been trying to solve the problem for a very long time. It seems that Kotest works better with Gradle than with Maven :(
I don't think that Maven is to blame, but the problem is probably that there is some dependency wrong or missing.
The TestEngineListener
mentioned in the error message is contained in the artifact kotest-framework-engine-jvm
which is transitively included, when you add kotest-runner-junit5-jvm
to your project.
So, I guess you just have to replace kotest-runner-junit5
in your pom with kotest-runner-junit5-jvm
.