我的目标是在没有@DirtiesContext
的测试中使用具有弹簧启动上下文的kafka测试容器。问题是没有为每个测试类分别启动容器,我不知道如何使用仅由特定测试类或方法生成的消息。
因此,我最终消耗的消息不属于正在运行的测试类。
一种解决方案可能是清除消息主题。我不知道如何执行此操作,我尝试重新启动容器,但接下来的测试无法连接到kafka。
我想到的第二个解决方案是在测试方法的开头创建消费者,并以某种方式记录最新消息,同时将调用其他测试人员。我已经能够使用嵌入式kafka做到这一点,但我不知道如何使用测试容器来做到这一点。
当前配置如下:
@TestConfiguration
public class KafkaContainerConfig {
@Bean(initMethod = "start", destroyMethod = "stop")
public KafkaContainer kafkaContainer() {
return new KafkaContainer("5.0.3");
}
@Bean
public KafkaAdmin kafkaAdmin(KafkaProperties kafkaProperties, KafkaContainer kafkaContainer) {
kafkaProperties.setBootstrapServers(List.of(kafkaContainer.getBootstrapServers()));
return new KafkaAdmin(kafkaProperties.buildAdminProperties());
}
}
带有将提供上述配置的注释
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(KafkaContainerConfig.class)
@EnableAutoConfiguration(exclude = TestSupportBinderAutoConfiguration.class)
@TestPropertySource("classpath:/application-test.properties")
@DirtiesContext
public @interface IncludeKafkaTestContainer {
}
在具有多个此类配置的测试类中,其外观类似于:
@IncludeKafkaTestContainer
@IncludePostgresTestContainer
@SpringBootTest(webEnvironment = RANDOM_PORT)
class SomeTest {
...
}
当前测试方法中的使用者是通过以下方式创建的:
KafkaConsumer<String, String> kafkaConsumer = createKafkaConsumer("topic_name");
ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(Duration.ofSeconds(1));
List<ConsumerRecord<String, String>> topicMsgs = Lists.newArrayList(consumerRecords.iterator());
并且:
public static KafkaConsumer<String, String> createKafkaConsumer(String topicName) {
Properties properties = new Properties();
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaContainer.getBootstrapServers());
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "testGroup_" + topicName);
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class)
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(properties);
kafkaConsumer.subscribe(List.of(topicName));
return kafkaConsumer;
}