Spring Kafka集成测试类如果不先执行就会失败

问题描述 投票:0回答:1

我编写了以下集成测试类:

@ActiveProfiles("test")
@SpringBootTest
@Testcontainers
class DomainCourseMapperServiceApplicationIntegrationTest {

    @Container
    static final KafkaContainer kafkaContainer =
            new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.4.3"));

    @DynamicPropertySource
    static void overrideKafkaProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers);
    }

    private static final String SCHEDULE_RAW_TOPIC = "schedule.raw";
    private static final String SCHEDULE_DOMAIN_TOPIC = "schedule.domain";

    KafkaTemplate<String, ScheduleRaw> scheduleRawProducer;
    Consumer<String, ScheduleDomain> scheduleDomainConsumer;

    @BeforeEach
    void setUp() {
        Map<String, Object> producerProps = KafkaTestUtils.producerProps(kafkaContainer.getBootstrapServers());
        producerProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        producerProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);

        ProducerFactory<String, ScheduleRaw> producerFactory = new DefaultKafkaProducerFactory<>(producerProps);
        scheduleRawProducer = new KafkaTemplate<>(producerFactory);

        Map<String, Object> scheduleDomainConsumerProps = KafkaTestUtils.consumerProps(kafkaContainer.getBootstrapServers(), "schedule-domain-test-group", "false");
        scheduleDomainConsumerProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        scheduleDomainConsumerProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
        scheduleDomainConsumerProps.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
        scheduleDomainConsumerProps.put(JsonDeserializer.TRUSTED_PACKAGES, "*");

        ConsumerFactory<String, ScheduleDomain> scheduleDomainConsumerFactory = new DefaultKafkaConsumerFactory<>(scheduleDomainConsumerProps);
        scheduleDomainConsumer = scheduleDomainConsumerFactory.createConsumer();
        scheduleDomainConsumer.subscribe(List.of(SCHEDULE_DOMAIN_TOPIC));

    }

    @AfterEach
    void tearDown() {
        scheduleDomainConsumer.close();
    }

    @Test
    void shouldConsumeScheduleRawAndProduceMappedScheduleDomainToDomainTopic() {
        // Given
        ...

        // When
        scheduleRawProducer.send(SCHEDULE_RAW_TOPIC, key, event);
        ConsumerRecord<String, ScheduleDomain> result = KafkaTestUtils.getSingleRecord(scheduleDomainConsumer, SCHEDULE_DOMAIN_TOPIC, Duration.ofSeconds(20));

        // Then
        ...
    }

}

当单独执行此测试类时,它会通过,但是当此测试类不单独运行时会出现问题,并且我在测试输出中得到以下堆栈跟踪:

java.lang.IllegalStateException: No records found for topic

at org.springframework.kafka.test.utils.KafkaTestUtils.getSingleRecord(KafkaTestUtils.java:181)

当测试类与其他测试类一起执行时(在项目中除了该测试类之外没有其他集成测试类 - 只有单元测试)它会失败,但只有在一种情况下 - 它不能首先执行。如果先执行此测试类,然后再执行其他测试类,则它通过。

我在

SCHEDULE_RAW_TOPIC
消费者中处理事件的行上添加了断点,以查看是否收到事件并且断点尚未触发 - 所以有两种可能性:
scheduleRawProducer
或消费者的问题。

我还尝试在测试类之上添加

@DirtiesContext
,但没有解决问题。

有人遇到过类似的问题或知道解决办法吗?


java spring spring-boot spring-kafka testcontainers
1个回答
0
投票

正如 Artem 在他的评论中所写,解决方案是添加

@DirtiesContext
- 在问题中我提到我已经尝试将
@DirtiesContext
放在类上,但我将其作为最后一个注释(从底部开始)。

放置后:

@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
作为类问题顶部的第一个注释已得到解决。

© www.soinside.com 2019 - 2024. All rights reserved.