6

我正在尝试将 Neo4j TestContainers 与 Kotlin、Spring Data Neo4j、Spring Boot 和 JUnit 5 一起使用。我有很多测试需要使用测试容器。理想情况下,我想避免在每个测试类中复制容器定义和配置。

目前我有类似的东西:

@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)

如何提取 databaseServer 定义和@TestConfiguration?我尝试了不同的方法来创建一个基类并让 ContainerTest 扩展它,但它不起作用。据我了解,静态属性不会在 Kotlin 中继承。

4

3 回答 3

1

我遇到了同样的问题(让 Spring Boot + Kotlin + Testcontainers 一起工作),在网上搜索了一段时间后,我发现了这个不错的解决方案:https ://github.com/larmic/testcontainers-junit5 。您只需要将它应用到您的数据库中。

于 2020-05-20T13:32:27.163 回答
1

下面是我在测试之间共享相同容器的解决方案。

@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() 仅初始化容器一次(在第一个子类测试执行时),然后在容器运行时不执行任何操作。

从理论上讲,我们不应该这样做,基于: https ://www.testcontainers.org/test_framework_integration/junit_5/

...在所有子类的所有测试都完成之前,不应关闭静态容器,但它不是那样工作的,我不知道为什么。很高兴对此有一些答案:)。

于 2021-04-23T14:10:07.310 回答
0

我在 Kotlin 和 spring boot 2.4.0 中遇到了非常相似的问题。重用一个测试容器配置的方式可以通过初始化器来实现,例如:https://dev.to/silaev/the-testcontainers-mongodb-module-and-spring-data-mongodb-in-action-53ng https : //nirajsonawane.github.io/2019/12/25/Testcontainers-With-Spring-Boot-For-Integration-Testing/(java版本)我还想使用拥有dynamicProperties的新方法,它在一个装箱中工作爪哇。在 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 
        }
    }
}

缺点是这个块在每个测试类中都有属性,这表明这里可能需要使用初始化方法。

于 2021-03-08T15:46:01.503 回答