我目前正在尝试在测试代码中更改某些Spring配置属性(这不是静态的,这就是原因)。
当我尝试使用@ContextConfiguration(initializers = [MyTestClass.Initializer::class])
解决我的问题时,出现了一件奇怪的事情。
在MyTestClass
中,我定义了这一点:
inner class Initializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
override fun initialize(applicationContext: ConfigurableApplicationContext) {
val values = TestPropertyValues.of("spring.datasource.url=" + postgresqlContainer.jdbcUrl)
values.applyTo(applicationContext)
}
}
(我在这里使用Testcontainers ...如何使它正常工作可能是一个单独的问题,请随时帮助我。)
postgresqlContainer
是我要访问的MyTestClass
的成员。当我运行测试时,我只会得到一个错误:
Caused by: java.lang.IllegalArgumentException: No argument provided for a required parameter: instance of fun com.example.MyTestClass.Initializer.<init>(): com.example.MyTestClass.Initializer
嗯,好的,所以我进行了一些调试,我认为是Spring的BeanUtils
无法处理Kotlin内部类。如果我从内部类中删除inner
关键字,那么BeanUtils可以创建一个实例–当然,这对我没有帮助,因为我需要访问外部类的属性。
我写了一个小测试来证实自己的怀疑:
import io.kotlintest.specs.StringSpec
import org.springframework.beans.BeanUtils
class Thing {
inner class InnerThing {
}
}
class BeanUtilTest: StringSpec({
"instantiate inner class" {
BeanUtils.instantiateClass(Thing.InnerThing::class.java)
// fails :-(
}
})
问题:有解决方法吗?如何在Kotlin的测试中覆盖应用程序属性?
答案 0 :(得分:1)
我只是碰到了这个问题,经过很长一段时间试图弄清楚是怎么回事,我终于想出了一个解决方案。
您可以按如下方式使用伴随对象(例如,对于MySql):
@Testcontainers
@ExtendWith(SpringExtension::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(initializers = [ExampleIntegrationTest.Companion.Initializer::class])
class ExampleIntegrationTest {
companion object {
@Container
@JvmField
val mySqlContainer = KotlinMySqlContainer()
class Initializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
override fun initialize(configurableApplicationContext: ConfigurableApplicationContext) {
TestPropertyValues.of(
"spring.datasource.url=" + mySqlContainer.jdbcUrl,
"spring.datasource.username=" + mySqlContainer.username,
"spring.datasource.password=" + mySqlContainer.password
).applyTo(configurableApplicationContext.environment)
}
}
}
...
}