I'm building a custom Spring context for my test in Spring Boot 2.7 (feel free to provide also a solution for newer versions). I'm not able to specify exact list of classes / auto-configuration needed for using ConfigurationProperties (kotlin, immutable data class, constructor binding) (spring cannot bind a constructor for data class). When I remove 'classes' (default configuration) field in SpringBootTest everything works fine.
I was trying to find a missing bean, I was digging into Spring internals, trying to build a bean dependency tree. I even listed almost all registered beans but without any success. I guess that the answer is around ValueObjectBinder. Does anyone resolve a similar problem?
Application.kt
@ConfigurationPropertiesScan
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
@ConfigurationProperties(prefix = "app")
@ConstructorBinding
data class FooProperties(
val foo: String,
val bar: String,
)
ApplicationTest.kt
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.NONE,
classes = [
FooProperties::class,
]
)
class ApplicationTest {
@Autowired
private lateinit var foo: FooProperties
@Test
fun contextLoads() {
println(foo)
}
}
application.yaml
app:
foo: abc
bar: cde
build.gradle (standard from a starter, spring boot 2.7, JDK 11, Kotlin, gradle build, I've just added spring-boot-configuration-processor)
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id 'org.springframework.boot' version '2.7.11'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'org.jetbrains.kotlin.jvm' version '1.6.21'
id 'org.jetbrains.kotlin.plugin.spring' version '1.6.21'
}
group = 'rg'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.withType(KotlinCompile) {
kotlinOptions {
freeCompilerArgs = ['-Xjsr305=strict']
jvmTarget = '11'
}
}
tasks.named('test') {
useJUnitPlatform()
}
This is part of exception I get:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fooProperties': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}