0

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: {}

Robert Gonciarz
  • 363
  • 2
  • 8
  • 15

0 Answers0