ClassNotFoundException for custom main test class while gradlew build

Hello. I am using Gradle for the first time in my home application. Version 8.10.
I am using Java 22 and Spring Boot 3.3.2.

There is a simple test class:

package ru.terentyev.taskmanagerstatisticsmain;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
class TaskManagerStatisticsApplicationTests {

	@Test
	void contextLoads() {
	}

}

When running in Eclipse IDE the tests pass successfully, but when running the ./gradlew clean build command I get the error:

org.gradle.api.internal.tasks.testing.TestSuiteExecutionException: Could not execute test class 'ru.terentyev.taskmanagerstatisticsmain.TaskManagerStatisticsApplicationTests'.
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:55)
	at java.base@22.0.2/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base@22.0.2/java.lang.reflect.Method.invoke(Method.java:580)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:92)
	at jdk.proxy1/jdk.proxy1.$Proxy4.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:183)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:132)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:121)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: org.gradle.internal.UncheckedException: java.lang.ClassNotFoundException: ru.terentyev.taskmanagerstatisticsmain.TaskManagerStatisticsApplicationTests
	at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:69)
	at org.gradle.internal.UncheckedException.throwAsUncheckedException(UncheckedException.java:42)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.loadClass(JUnitPlatformTestClassProcessor.java:175)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.access$100(JUnitPlatformTestClassProcessor.java:62)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.execute(JUnitPlatformTestClassProcessor.java:109)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.execute(JUnitPlatformTestClassProcessor.java:99)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:54)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:53)
	... 16 more
Caused by: java.lang.ClassNotFoundException: ru.terentyev.taskmanagerstatisticsmain.TaskManagerStatisticsApplicationTests
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:529)
	at java.base/java.lang.Class.forName(Class.java:508)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.loadClass(JUnitPlatformTestClassProcessor.java:173)
	... 21 more

I tried changing the classpath in different ways, including specifying it in build.gradle.kts. The tests are located at TaskManagerStatistics/src/test/java/ru/terentyev/TaskManagerStatisticsApplicationTests.
Here is my build.gradle.kts:

plugins {
	java
	war
	id("org.springframework.boot") version "3.3.2"
	id("io.spring.dependency-management") version "1.1.6"
}

group = "ru.terentyev"
version = "0.0.1-SNAPSHOT"

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(22)
	}
}

configurations {
	compileOnly {
		extendsFrom(configurations.annotationProcessor.get())
	}
}

repositories {
	mavenCentral()
}

dependencies {
	
	implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
	implementation("org.springframework.boot:spring-boot-starter-web")
	implementation("org.springframework.kafka:spring-kafka:3.2.3")	
	compileOnly("org.projectlombok:lombok")
	// developmentOnly("org.springframework.boot:spring-boot-docker-compose")
	annotationProcessor("org.projectlombok:lombok")
	providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
	testImplementation("org.springframework.boot:spring-boot-starter-test")
	implementation("org.springframework.boot:spring-boot-starter")
}

tasks.named<Test>("test") {
    useJUnitPlatform()
}

tasks.withType<JavaCompile> {
    options.compilerArgs.add("-parameters")
}

What’s interesting to me is that if you rename the class and class file (for example, from *Tests.class to *Test.class), the exception will contain the new class name.

How to fix this error? I couldn’t find anything on the Internet. Sorry for my English. I appreciate any help.

From a very quick look I only see one fishy thing that is probably not related.
So can you maybe knit a full MCVE?

The fishy thing if you are curious, is the Spring dependency management plugin. It is a relict from times when Gradle did not have built-in BOM support and by now does more harm than good. Even the maintainer of that plugin recommends not to use it anymore but instead the built-in BOM support using platform(...).

Here I created a simple application via Spring Initializr with a single Spring Web dependency and the error is reproduced in it.
When generating the initial project I used the settings as in the screenshot:

I also tried to change io.spring.dependency-managment to spring-boot-dependencies, but the error still remained. Now my build.gradle.kts looks like this:

plugins {
	java
	war
	id("org.springframework.boot") version "3.3.2"
	//id("io.spring.dependency-management") version "1.1.6"
}

group = "ru.terentyev"
version = "0.0.1-SNAPSHOT"

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(22)
	}
}

configurations {
	compileOnly {
		extendsFrom(configurations.annotationProcessor.get())
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation(platform("org.springframework.boot:spring-boot-dependencies:3.3.2"))
	implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
	implementation("org.springframework.boot:spring-boot-starter-web")
	implementation("org.springframework.kafka:spring-kafka:3.2.3")	
	compileOnly("org.projectlombok:lombok:1.18.34")
	// developmentOnly("org.springframework.boot:spring-boot-docker-compose")
	annotationProcessor("org.projectlombok:lombok:1.18.34")
	implementation("org.springframework.boot:spring-boot-starter-tomcat")
	testImplementation("org.springframework.boot:spring-boot-starter-test")
	implementation("org.springframework.boot:spring-boot-starter")
}

tasks.named<Test>("test") {
    useJUnitPlatform()
}

tasks.withType<JavaCompile> {
    options.compilerArgs.add("-parameters")
}

Unfortunately your MCVE lacks the V part.
It runs fine here without any CNFE.
Can you maybe share a build --scan where your above MCVE fails,
then I can create one where it runs and we can maybe compare.

https://scans.gradle.com/s/fawi3qzrehpeq

Hm, I mainly see two major differences.

I try with Adoptium Java 22, you with Oracle Java 22.
I highly doubt that makes a difference, but you could try using Adoptium and see whether it changes something

The other thing is, that you are using a path that is potentially problematic in three aspects. It has a space in it, it has cyrillic characters in it, and it is a OneDrive synced folder. All these individually I know can break some things, independent of whether it is Gradle or Jupiter related or not. So I suggest you eradicate all three of these aspects and try again. If it solves it, it might be worth finding out which aspect exactly is the problem and who exactly has a problem with it to eventually report a bug to get it fixed.

Thank you very much! Indeed, I moved the project to a folder whose path contains only Latin characters without spaces and now everything works fine! You saved my project! :slight_smile:

I tried different options and found out that it is the use of Cyrillic (Russian) characters that causes the error. There is no error due to spaces.

I’ve had a deeper look and found what the exact problem is and reported it at Tests unrunnable when in directory with characters not encodable by system encoding · Issue #30391 · gradle/gradle · GitHub