带有 testcontainers 和 jOOQ 的 Spring Boot 不会注入 DSL 上下文
Posted
技术标签:
【中文标题】带有 testcontainers 和 jOOQ 的 Spring Boot 不会注入 DSL 上下文【英文标题】:Spring boot with testcontainers and jOOQ doesn't inject DSL context 【发布时间】: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")
【问题讨论】:
Seems related 【参考方案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
【讨论】:
以上是关于带有 testcontainers 和 jOOQ 的 Spring Boot 不会注入 DSL 上下文的主要内容,如果未能解决你的问题,请参考以下文章
带有 h2 和 jooq 的 JdbcSQLSyntaxErrorException
带有 Gradle 和 Kotlin 的 JOOQ 不生成文件
我可以在 JDBC URL 模式下使用带有自定义 Dockerfile 的 Testcontainers 吗?