在测试中不能多次使用@KafkaListener

时间:2019-09-03 14:35:26

标签: spring-kafka spring-cloud-stream spring-kafka-test

我们正在尝试测试cloud-stream-kafka应用程序,并且在测试中,我们有多种发送消息的测试方法,以及一个@KafkaListener等待响应。

但是,第一个测试倾向于通过,第二个测试倾向于失败。

任何指针将不胜感激。

@SpringBootTest(properties = "spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}")
@EmbeddedKafka(topics = "input", partitions = 1)
@DirtiesContext
class EmbeddedKafkaListenerTest {

  private CountDownLatch latch;

  private String message;

  @BeforeEach
  void setUp() {
    this.message = null;
    this.latch = new CountDownLatch(1);
  }

  @Test
  void testSendFirstMessage(@Autowired KafkaTemplate<String, byte[]> template)
      throws InterruptedException {
    template.send("input", "Hello World 1".getBytes());
    assertTrue(latch.await(10, TimeUnit.SECONDS));
    assertEquals("Hello World 1", message);
  }

  @Test
  void testSendSecondMessage(@Autowired KafkaTemplate<String, byte[]> template)
      throws InterruptedException {
    template.send("input", "Hello World 2".getBytes());
    assertTrue(latch.await(10, TimeUnit.SECONDS));
    assertEquals("Hello World 2", message);
  }

  @KafkaListener(topics = "input", id = "kafka-listener-consumer")
  void listener(Message<byte[]> message) {
    this.message = new String(message.getPayload(), StandardCharsets.UTF_8);
    this.latch.countDown();
  }
}

似乎每个测试都在注册@KafkaListener的实例,因为我们注意到使用id值会导致java.lang.IllegalStateException: Another endpoint is already registered with id 'kafka-listener-consumer'

当使用的消息传递框架是RabbitMQ时,我使用@RabbitListener做了类似的测试。我希望我可以做类似的事情,因为某些测试用例涉及等待无消息发布,而我们可以使用assertFalse(latch.await(10, TimeUnit.SECONDS))

1 个答案:

答案 0 :(得分:0)

我认为您的@KafkaListener方法应该进入@Configuration类,否则的确是每个测试方法都实例化了EmbeddedKafkaListenerTest,因此@KafkaListener的解析程度很高有了测试方法。

另一种方法是使用@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD),因此您不仅将为每个测试方法拥有新鲜的EmbeddedKafkaListenerTest实例,而且还将拥有Spring ApplicationContext

还有一种使用@TestInstance(TestInstance.Lifecycle.PER_CLASS)的方法,因此整个测试服将只有一个EmbeddedKafkaListenerTest,而您的@KafkaListener不会被解析多次。