在我的测试中,我有两个容器使用 @Testcontainers
和 Junit5,一个 Kafka
和一个 KafkaConnect
。
@Container
private final KafkaContainer kafka = new KafkaContainer()
.withNetwork(network)
.withNetworkAliases("kafka");
@Container
private final GenericContainer KafkaConnect =
new GenericContainer("confluentinc/cp-kafka-connect:latest")
.withEnv("CONNECT_BOOTSTRAP_SERVERS", "kafka:9092")
.withEnv("CONNECT_REST_PORT", 8083)
.withNetwork(network)
...
当我执行测试时,我发现一个错误,因为 kafkaConnect
中的 Kafka Connect 服务未正确启动(映射端口 8083 未监听)。这是因为 kafkaConnect
在 kafka
之前启动,并且在 kafkaConnect
执行期间到达 kafka:9092
url 时没有由于 kafka
尚未运行,因此获得了响应。
然后,我试图推迟 kafkaConnect
启动以等待 kafka
以确保 kafka:9092
可用性。
我尝试了不同的方法来做到这一点,但我没有解决问题。 我尝试添加一些配置。
启动超时
。据我所知,此配置不会推迟启动操作。它只是增加了检查容器是否启动的周期。
.withStartupTimeout(Duration.of(240, SECONDS))
我还为 waitingFor
尝试了一些配置,例如基于超时的配置,正如预期的那样,它会产生与 withStartupTimeout
相同的结果
.waitingFor(Wait.defaultWaitStrategy().withStartupTimeout(...))
或基于端口,这不能解决我的问题,因为它不指向 kafka
容器,而是指向 kafkaConnect
。
.waitingFor(Wait.forHttp("http://kafka:9092"))
我也尝试添加一些启动尝试,但它没有解决问题,因为 kafkaConnect
有时会重新启动,但总是在 kafka
之前。
作为解决方案,我删除了 kafkaConnect
声明的 @Container
以便手动管理其生命周期,因此我添加了明确的开始测试用例,见下文
@Test
test() {
kafkaConnect.start();
...
}
这确保 kafkaConnect
在 kafka
之后启动。但是,我没有找到在容器定义期间通过策略、策略或类似的方式定义顺序的解决方案,以便添加容器之间的依赖关系并避免命令式和手动的生命周期管理。
这可能吗?
最佳答案
import org.junit.rules.RuleChain;
// @Container <-- Remove annotation.
private final KafkaContainer kafka = new KafkaContainer()...;
// @Container <-- Remove annotation.
private final GenericContainer kafkaConnect =
new GenericContainer("confluentinc/cp-kafka-connect:latest")
.withEnv("CONNECT_BOOTSTRAP_SERVERS", "kafka:9092")
...;
// Start the containers in the correct order. Prevents
// "Mapped port can only be obtained after the container is started"
// error.
@Rule
public final RuleChain chain =
RuleChain
// Started first.
.outerRule(kafka)
// Started later.
.around(kafkaConnect);
关于junit - 有序启动和等待容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55515090/