【问题标题】:Spring boot with testcontainers and jOOQ doesn't inject DSL context带有 testcontainers 和 jOOQ 的 Spring Boot 不会注入 DSL 上下文
【发布时间】:2020-10-17 03:03:54
【问题描述】:

我对 spring boot + jOOQ 和 testcontainers 有一些问题。 DSL 上下文不会注入到我的测试类中。

我为使用SQLContainer做了一些准备

class SpringTestContainer: PostgreSQLContainer<SpringTestContainer> {

    private val postgreSqlPort = 5432
    private val db = "m4"

    companion object {
        var instance: SpringTestContainer? = null

        fun get(): SpringTestContainer {
            if(instance == null) {
                instance = SpringTestContainer()
            }

            return instance!!
        }
    }

    override fun getDatabaseName(): String = db

    constructor() : this("registry.dev.tskad.stdev.ru/m4/db:latest")

    constructor(dockerImageName: String) : super(dockerImageName){
        withImagePullPolicy(PullPolicy.alwaysPull())
        addExposedPort(postgreSqlPort)
        waitStrategy = LogMessageWaitStrategy()
            .withRegEx(".*database system is ready to accept connections.*\\s")
            .withTimes(1)
            .withStartupTimeout(Duration.of(30, ChronoUnit.SECONDS))
    }

    override fun getJdbcUrl(): String {
        return String.format("jdbc:postgresql://%s:%d/%s", containerIpAddress, getMappedPort(postgreSqlPort), databaseName)
    }

    override fun waitUntilContainerStarted() {
        getWaitStrategy().waitUntilReady(this)
    }

    override fun getLivenessCheckPorts(): Set<Int?> {
        return HashSet(getMappedPort(postgreSqlPort))
    }

}

然后我创建了一些抽象来扩展我的集成测试类

@ContextConfiguration(initializers = [SpringIntegrationTest.Initializer::class])
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@JooqTest
abstract class SpringIntegrationTest {

    @get:Rule
    var postgreSQLContainer = SpringTestContainer.get()

    inner class Initializer: ApplicationContextInitializer<ConfigurableApplicationContext> {
        override fun initialize(applicationContext: ConfigurableApplicationContext) {
            with(applicationContext.environment.systemProperties) {
                put("spring.datasource.url", postgreSQLContainer.jdbcUrl)
                put("spring.datasource.username", postgreSQLContainer.username)
                put("spring.datasource.password", postgreSQLContainer.password)
            }
        }
    }

}

然后我实现了测试类

@ExtendWith(SpringExtension::class)
class TransactionRepositoryImplTest: SpringIntegrationTest() {

    @Autowired
    private var dslContext: DSLContext? = null

    private var transactionRepository: TransactionRepository? = null

    @Before
    fun setUp() {
        assertThat(dslContext).isNotNull
        transactionRepository = TransactionRepositoryImpl(dslContext!!)
    }

    @After
    fun tearDown() {

    }

    @Test
    fun findTransactionData() {
        transactionRepository?.findTransactionByVehicleUuid(null).apply {
            assertNull(this)
        }

    }

}

当我开始这个类的测试时 - 测试失败,因为断言没有通过。 这里是测试报告https://pastebin.com/0HeqDcCT

那么..怎么不可能?我看到了一些关于这个堆栈的指南(Spring/jOOQ/TestContainers)。他们都在工作。也许我错过了一些测试依赖项?如果您有此案例的经验 - 请分享您的解决方案。我将不胜感激。

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.springframework.boot:spring-boot-starter-jooq")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.cloud:spring-cloud-starter-consul-config")
    implementation("org.springframework.cloud:spring-cloud-stream")
    implementation("org.springframework.cloud:spring-cloud-stream-binder-kafka")
    implementation("org.springframework.kafka:spring-kafka")
    implementation("org.springframework.boot:spring-boot-starter-amqp")
    implementation ("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.3")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.10.3")
    runtimeOnly("org.postgresql:postgresql:42.2.12")
    jooqGeneratorRuntime("org.postgresql:postgresql:42.2.12")
    annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
        exclude(module = "junit")
    }
    testImplementation("com.ninja-squad:springmockk:2.0.1")
    testImplementation("org.springframework.cloud:spring-cloud-stream-test-support")
    testImplementation("org.springframework.kafka:spring-kafka-test")
    testImplementation("org.springframework.amqp:spring-rabbit-test")
    testImplementation("org.testcontainers:postgresql:1.14.3")
}

【问题讨论】:

标签: spring-boot kotlin jooq spring-boot-test testcontainers


【解决方案1】:

我可能遗漏了一些东西,但在该设置中,您必须手动运行 postgreSQLContainer.start() 某处。例如,它可以在@BeforeAll 中完成。

【讨论】:

  • 很遗憾,没有效果:(
【解决方案2】:

我找到了解决方案。正确的方法是覆盖测试容器实现的start 方法,并将凭据放入容器数据库的系统属性中。

这是工作代码:

class SpringTestContainer: PostgreSQLContainer<SpringTestContainer> {

    private val postgreSqlPort = 5432
    private val db = "m4"

    companion object {
        var instance: SpringTestContainer? = null

        fun get(): SpringTestContainer {
            if(instance == null) {
                instance = SpringTestContainer()
            }

            return instance!!
        }
    }

    override fun getDatabaseName(): String = db

    constructor() : this("registry.dev.tskad.stdev.ru/m4/db:latest")

    constructor(dockerImageName: String) : super(dockerImageName){
        withImagePullPolicy(PullPolicy.alwaysPull())
        addExposedPort(postgreSqlPort)
        waitStrategy = LogMessageWaitStrategy()
            .withRegEx(".*database system is ready to accept connections.*\\s")
            .withTimes(1)
            .withStartupTimeout(Duration.of(30, ChronoUnit.SECONDS))
    }

    override fun getJdbcUrl(): String {
        return String.format("jdbc:postgresql://%s:%d/%s", containerIpAddress, getMappedPort(postgreSqlPort), databaseName)
    }

    override fun waitUntilContainerStarted() {
        getWaitStrategy().waitUntilReady(this)
    }

    override fun getLivenessCheckPorts(): Set<Int?> {
        return HashSet(getMappedPort(postgreSqlPort))
    }

    override fun start() {
        super.start()
        val container = get()
        System.setProperty("DB_URL", container.jdbcUrl)
        System.setProperty("DB_USERNAME", container.username)
        System.setProperty("DB_PASSWORD", container.password)
    }
}
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@SpringBootTest(properties = ["spring.cloud.consul.enabled = false"])
@EnableAutoConfiguration(exclude = [
    RabbitAutoConfiguration::class,
    KafkaAutoConfiguration::class
])
class TransactionRepositoryImplTest {

    @get:Rule
    var postgreSQLContainer = SpringTestContainer.get()

    @Autowired
    private lateinit var dslContext: DSLContext

    @Autowired
    private lateinit var transactionRepository: TransactionRepository

    @MockkBean
    private lateinit var connectionFactory: ConnectionFactory // this is the mock for rabbit connection. U may ignore it.

    @Test
    fun contextLoads() {
        Assertions.assertNotNull(dslContext)
        Assertions.assertNotNull(transactionRepository)
    }

}

然后需要修复tests目录下的application.yml

spring:
  datasource:
    platform: postgres
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
    driverClassName: org.postgresql.Driver

【讨论】:

    猜你喜欢
    • 2018-10-04
    • 1970-01-01
    • 2023-03-04
    • 2021-06-30
    • 2015-08-09
    • 1970-01-01
    • 2021-10-14
    • 2015-03-04
    • 2019-10-21
    相关资源
    最近更新 更多