如何使用JUnit5在Kotlin中创建TestContainers基测试类
我正在尝试将Neo4jTestContainers与Kotlin、SpringDataNeo4j、SpringBoot和JUnit5一起使用。我有很多测试需要使用测试容器。理想情况下,我希望避免在每个测试类中复制容器定义和配置 目前我有一些类似于:如何使用JUnit5在Kotlin中创建TestContainers基测试类,kotlin,spring-data-neo4j,testcontainers,Kotlin,Spring Data Neo4j,Testcontainers,我正在尝试将Neo4jTestContainers与Kotlin、SpringDataNeo4j、SpringBoot和JUnit5一起使用。我有很多测试需要使用测试容器。理想情况下,我希望避免在每个测试类中复制容器定义和配置 目前我有一些类似于: @Testcontainers @DataNeo4jTest @Import(Neo4jConfiguration::class, Neo4jTestConfiguration::class) class ContainerTest(@Autowir
@Testcontainers
@DataNeo4jTest
@Import(Neo4jConfiguration::class, Neo4jTestConfiguration::class)
class ContainerTest(@Autowired private val repository: XYZRepository) {
companion object {
const val IMAGE_NAME = "neo4j"
const val TAG_NAME = "3.5.5"
@Container
@JvmStatic
val databaseServer: KtNeo4jContainer = KtNeo4jContainer("$IMAGE_NAME:$TAG_NAME")
.withoutAuthentication()
}
@TestConfiguration
internal class Config {
@Bean
fun configuration(): Configuration = Configuration.Builder()
.uri(databaseServer.getBoltUrl())
.build()
}
@Test
@DisplayName("Create xyz")
fun testCreateXYZ() {
// ...
}
}
class KtNeo4jContainer(val imageName: String) : Neo4jContainer<KtNeo4jContainer>(imageName)
@Testcontainers
@DataNeo4jTest
@导入(NEO4JCConfiguration::class,Neo4jTestConfiguration::class)
类ContainerTest(@Autowired private val repository:XYZRepository){
伴星{
const val IMAGE_NAME=“neo4j”
const val TAG_NAME=“3.5.5”
@容器
@JvmStatic
val数据库服务器:KtNeo4jContainer=KtNeo4jContainer($IMAGE\u NAME:$TAG\u NAME))
.没有身份验证()
}
@测试配置
内部类配置{
@豆子
fun configuration():configuration=configuration.Builder()
.uri(databaseServer.getBoltUrl())
.build()
}
@试验
@DisplayName(“创建xyz”)
有趣的testCreateXYZ(){
// ...
}
}
类KtNeo4jContainer(val imageName:String):Neo4jContainer(imageName)
如何提取databaseServer定义和@TestConfiguration?我尝试了创建基类并让ContainerTest扩展它的不同方法,但它不起作用。据我所知,Kotlin中不会继承静态属性。我也遇到过同样的问题(使Spring Boot+Kotlin+Testcontainers协同工作),在搜索web(相当长时间)后,我发现了这个不错的解决方案:。您只需将其应用到数据库中即可 我在Kotlin和spring boot 2.4.0中遇到了非常类似的问题。 可以通过初始化器实现重用一个testcontainer配置的方法,例如: 或(java版本) 我还想使用具有dynamicProperties的新方法,它是用java编写的盒装程序实现的。在Kotlin中,我做了类似的事情(出于某种原因,我无法使@Testcontainer注释工作)。这不是一个非常优雅但对我来说非常简单的解决方案: MongoContainerConfig类:
import org.testcontainers.containers.MongoDBContainer
class MongoContainerConfig {
companion object {
@JvmStatic
val mongoDBContainer = MongoDBContainer("mongo:4.4.2")
}
init {
mongoDBContainer.start()
}
}
测试等级:
@SpringBootTest(
classes = [MongoContainerConfig::class]
)
internal class SomeTest {
companion object {
@JvmStatic
@DynamicPropertySource
fun setProperties(registry: DynamicPropertyRegistry) {
registry.add("mongodb.uri") {
MongoContainerConfig.mongoDBContainer.replicaSetUrl
}
}
}
缺点是每个测试类中都有属性,这表明这里可能需要使用初始值设定项的方法。下面是我在测试之间共享同一容器的解决方案
@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
abstract class IntegrationTest {
companion object {
@JvmStatic
private val mongoDBContainer = MongoDBContainer(DockerImageName.parse("mongo:4.0.10"))
.waitingFor(HostPortWaitStrategy())
@BeforeAll
@JvmStatic
fun beforeAll() {
mongoDBContainer.start()
}
@JvmStatic
@DynamicPropertySource
fun registerDynamicProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.data.mongodb.host", mongoDBContainer::getHost)
registry.add("spring.data.mongodb.port", mongoDBContainer::getFirstMappedPort)
}
}
}
这里的关键是不要使用@Container注释,因为它将在第一个测试子类执行所有测试后关闭刚刚创建的容器。
beforeAll()中的方法start()只初始化容器一次(在第一个子类测试执行时),然后在容器运行时不执行任何操作
理论上,我们不应该做这种黑客行为,基于:
…在所有子类的所有测试完成之前,不应该关闭静态容器,但它不是这样工作的,我不知道为什么。很高兴能得到一些答案:)。请在答案中包含相关信息;目前,这基本上是一个链接的答案,这些都是不赞成的,因为(除其他原因外)外部信息会腐烂掉。这个链接不会腐烂