如何使用 JUnit 5 在 Kotlin 中创建 TestContainers 基测试类
Posted
技术标签:
【中文标题】如何使用 JUnit 5 在 Kotlin 中创建 TestContainers 基测试类【英文标题】:How to create a TestContainers base test class in Kotlin with JUnit 5 【发布时间】:2019-09-29 15:58:30 【问题描述】:我正在尝试将 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 中不会继承静态属性。
【问题讨论】:
【参考方案1】:我遇到了同样的问题(让 Spring Boot + Kotlin + Testcontainers 一起工作),在网上搜索了一段时间后(相当)我找到了这个不错的解决方案:https://github.com/larmic/testcontainers-junit5。您只需要将它应用到您的数据库中。
【讨论】:
请在您的回答中包含相关信息;目前,它基本上是一个仅链接的答案,这些都是不受欢迎的,因为(除其他原因外)外部信息会腐烂。 此链接不会失效。 :D【参考方案2】:下面是我在测试之间共享相同容器的解决方案。
@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/
...在所有子类的所有测试都完成之前,不应关闭静态容器,但它不是那样工作的,我不知道为什么。很高兴对此有一些答案:)。
【讨论】:
【参考方案3】:我在 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 的新方法,它在 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
缺点是这个块在每个测试类中都有属性,这表明这里可能需要使用初始化器的方法。
【讨论】:
以上是关于如何使用 JUnit 5 在 Kotlin 中创建 TestContainers 基测试类的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Kotlin 中创建一个打开新活动(Android Studio)的按钮?
如何在 xml 和 kotlin 组合中创建类似布局的计算器