弹簧启动 + Liquibase + Gradle + 测试容器 / 找不到配置



所以,我一直试图在工作中开始从Maven迁移到Gradle,但现在我遇到了一个严重的问题,我似乎无法解决这个问题。

我基本上只是想为我的测试运行一些简单的liquibase迁移,为此我旋转了两个测试容器。一个用于rabbitmqexchange,一个用于postgres DB。

我已经使用这里描述的一个小变通方法设置了postgres容器:使用Kotlin和Testcontainers 测试Spring Boot应用程序

我已经尝试了一千种方法,搜索了所有相关的问题,但我似乎不知道问题是什么…

以下是使用Gradle 6.7.1:的设置

build.gradle.kts

plugins {
id("org.springframework.boot") version "2.4.0"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
application
kotlin("jvm") version "1.4.20"
id("org.jetbrains.kotlin.plugin.spring") version "1.4.20"
id("org.liquibase.gradle") version "2.0.4"
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.cloud:spring-cloud-stream:3.0.9.RELEASE")
implementation("org.springframework.cloud:spring-cloud-stream-binder-rabbit:3.0.9.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-configuration-processor")
implementation("org.liquibase:liquibase-core:4.0.0")
//    liquibaseRuntime("org.liquibase:liquibase-core:4.0.0")
runtimeOnly("org.postgresql:postgresql:42.2.18")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.7.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0")
testImplementation("org.testcontainers:testcontainers:1.15.0")
testImplementation("org.testcontainers:junit-jupiter:1.15.0")
testImplementation("org.testcontainers:rabbitmq:1.15.0")
testImplementation("org.testcontainers:postgresql:1.15.0")
}
description = "my-project"
java.sourceCompatibility = JavaVersion.VERSION_1_8
application {
mainClass.set("path/to/the/main/class")
}
tasks.named<Test>("test") {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
tasks.register<Copy>("copyJarToTargetDir") {
mustRunAfter("build")
val outputJar = "$buildDir/libs"
val targetDir = "$projectDir/target"
from(outputJar)
include("*.jar")
into(targetDir)
}
tasks.register<Delete>("deleteTargetDir") {
mustRunAfter("clean")
delete("$projectDir/target")
}
tasks.named("build") {
finalizedBy("copyJarToTargetDir")
}
tasks.named("clean") {
finalizedBy("deleteTargetDir")
}

基础测试:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@Testcontainers
class PartnerEdgeServiceApplicationBaseTests {
@Autowired
lateinit var vehicleRepository: VehicleRepository
@Autowired
lateinit var vehicleStreamChannel: VehicleDataChannel
@LocalServerPort
private val port: Int = 0
@Test
fun `check application`() {
println("Howdy, Partners!")
}
}

有问题的测试:

class MessageSinkTest : ApplicationBaseTests() {
companion object {
@Container
val rabbitMQContainer = RabbitMQContainer("rabbitmq:alpine")
@Container
val postgresContainer: KPostgreSQLContainer = KPostgreSQLContainer("postgres:10.11-alpine")
@JvmStatic
@DynamicPropertySource
fun properties(registry: DynamicPropertyRegistry) {
registry.add("spring.datasource.url", postgresContainer::getJdbcUrl)
registry.add("spring.datasource.password", postgresContainer::getPassword)
registry.add("spring.datasource.username", postgresContainer::getUsername)
registry.add("spring.rabbitmq.addresses", rabbitMQContainer::getAmqpUrl)
registry.add("spring.rabbitmq.username", rabbitMQContainer::getAdminUsername)
registry.add("spring.rabbitmq.password", rabbitMQContainer::getAdminPassword)
registry.add("spring.liquibase.url", postgresContainer::getJdbcUrl)
registry.add("spring.liquibase.user", postgresContainer::getUsername)
registry.add("spring.liquibase.password", postgresContainer::getPassword)
}
}
@Test
@DisplayName("Should extract the vehicle data and persist in the DB")
fun test1() {
val id = "id"
val locationId = 1L
val numberPlate = "Some plate"
val buildSeries = "VW_TIGUAN"
val fuel = 75
val fuelType = "GASOLINE"
vehicleStreamChannel.input().send(
GenericMessage(
VehicleDataStreamDto(
id = id,
locationId = locationId,
numberPlate = numberPlate,
buildSeries = buildSeries,
fuel = fuel,
fuelType = fuelType
)
)
)
val persistedVehicle = vehicleRepository.findByIdOrNull(vin)
assertEquals(id, persistedVehicle?.id)
}
}

和应用程序。yml:

server:
servlet:
context-path: /my-project
streaming:
retries: 5
concurrency: 15
amqpGroupName: my_project
spring:
jpa:
hibernate:
ddl-auto: none
database-platform: org.hibernate.dialect.PostgreSQL94Dialect
liquibase:
url: ${spring.datasoure.url}
user: ${spring.datasource.username}
password: ${spring.datasoure.password}
contexts: environment-name-will-be-placed-here
change-log: classpath:/db/changelog/db.changelog-master.xml
datasource:
driver-class-name: org.postgresql.Driver
cloud:
stream:
rabbit:
bindings:
vehiclestream:
consumer:
declareExchange: true
---
spring:
jpa:
database-platform: org.hibernate.dialect.PostgreSQL94Dialect
hibernate:
ddl-auto: none
config:
activate:
on-profile: local

当我运行测试时,我得到以下日志:

Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:99)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:350)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:355)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$7(ClassBasedTestDescriptor.java:350)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:313)
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:647)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:349)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$4(ClassBasedTestDescriptor.java:270)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:269)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$2(ClassBasedTestDescriptor.java:259)
at java.util.Optional.orElseGet(Optional.java:267)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$3(ClassBasedTestDescriptor.java:258)
at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:101)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:100)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:65)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:111)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:111)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:79)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:133)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.ChangeLogParseException: The file classpath:/db/changelog/db.changelog-master.xml was not found in
- a bunch of paths

我的db.changelog-master.xml位于以下位置(从项目的根目录(:

src/main/resources/db/changelog/db.changelog-master.xml

因此,这个错误真的没有意义,或者我错过了什么(显然是这样…(。无论如何,任何形式的帮助都非常感谢!!

更新:

所以,我确实做了一点改变。我把这两个依赖项implementation("org.liquibase:liquibase-core:4.0.0")换成了liquibaseRuntime("org.liquibase:liquibase-core:4.0.0"),并在application.yml上删除了jpa.properties。我确实得到了一个不同的错误:

{"@timestamp":"2020-11-29T09:05:08.612+01:00","@version":"1","logmessage":"SQL Error: 0, SQLState: 42P01","logger_name":"org.hibernate.engine.jdbc.spi.SqlExceptionHelper","thread_name":"Test worker","level":"WARN","level_value":30000,"vin":"vin"}
{"@timestamp":"2020-11-29T09:05:08.614+01:00","@version":"1","logmessage":"ERROR: relation "vehicles" does not existn  Position: 290","logger_name":"org.hibernate.engine.jdbc.spi.SqlExceptionHelper","thread_name":"Test worker","level":"ERROR","level_value":40000,"vin":"vin"}
{"@timestamp":"2020-11-29T09:05:08.617+01:00","@version":"1","logmessage":"HHH000327: Error performing load command","logger_name":"org.hibernate.event.internal.DefaultLoadEventListener","thread_name":"Test worker","level":"INFO","level_value":20000,"stack_trace":"org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Exception thrown while invoking VehicleDataSink#processData[1 args]; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; 

因此,为了将来的参考:这个问题不是任何特定于gradle/liquibase的问题。事实很简单,我在Intellij中一步创建了目录db/changelog,它创建了一个目录db.changelog,而/changelogdb的子目录。经过两个不同的步骤,一切都很好!

相关内容

最新更新