Spring Boot 2.xを使用して開発しているKafkaリスナーの単体テストを作成しようとしています。単体テストなので、Zookeeperのインスタンスである完全なKafkaサーバーを起動したくありません。そこで、Spring Embedded Kafkaを使用することにしました。
リスナーの定義は非常に基本的です。
@Component
public class Listener {
private final CountDownLatch latch;
@Autowired
public Listener(CountDownLatch latch) {
this.latch = latch;
}
@KafkaListener(topics = "sample-topic")
public void listen(String message) {
latch.countDown();
}
}
また、メッセージを受信した後、latch
カウンターがゼロに等しいことを確認するテストは非常に簡単です。
@RunWith(SpringRunner.class)
@SpringBootTest
@DirtiesContext
@EmbeddedKafka(topics = { "sample-topic" })
@TestPropertySource(properties = { "spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}" })
public class ListenerTest {
@Autowired
private KafkaEmbedded embeddedKafka;
@Autowired
private CountDownLatch latch;
private KafkaTemplate<Integer, String> producer;
@Before
public void setUp() {
this.producer = buildKafkaTemplate();
this.producer.setDefaultTopic("sample-topic");
}
private KafkaTemplate<Integer, String> buildKafkaTemplate() {
Map<String, Object> senderProps = KafkaTestUtils.producerProps(embeddedKafka);
ProducerFactory<Integer, String> pf = new DefaultKafkaProducerFactory<>(senderProps);
return new KafkaTemplate<>(pf);
}
@Test
public void listenerShouldConsumeMessages() throws InterruptedException {
// Given
producer.sendDefault(1, "Hello world");
// Then
assertThat(latch.await(10L, TimeUnit.SECONDS)).isTrue();
}
}
残念ながら、テストは失敗し、理由を理解できません。 KafkaEmbedded
のインスタンスを使用して、注釈@KafkaListener
でマークされたメソッドをテストすることはできますか?
すべてのコードは私のGitHubリポジトリで共有されます kafka-listener 。
ありがとうございます。
おそらく、コンシューマーにトピック/パーティションが割り当てられる前にメッセージを送信しているでしょう。プロパティを設定...
spring:
kafka:
consumer:
auto-offset-reset: earliest
...デフォルトはlatest
です。
これは、コンソールコンシューマで--from-beginning
を使用するようなものです。
[〜#〜] edit [〜#〜]
ああ;ブートのプロパティを使用していません。
追加する
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
EDIT2
ところで、送信が成功したことをアサートするには、おそらくget(10L, TimeUnit.SECONDS)
(Future<>
)の結果に対してtemplate.send()
も実行する必要があります。
EDIT
テストのためだけにオフセットリセットを無効にするには、ブローカーアドレスに対して行ったのと同じことを実行できます。
@Value("${spring.kafka.consumer.auto-offset-reset:latest}")
private String reset;
...
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, this.reset);
そして
@TestPropertySource(properties = { "spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}",
"spring.kafka.consumer.auto-offset-reset=earliest"})
ただし、このプロパティはグループが初めて消費するときにのみ適用されることに注意してください。アプリが起動するたびに常に最後から開始するには、起動中に最後までシークする必要があります。
また、enable.auto.commit
をfalse
に設定することをお勧めします。これにより、コンテナは、タイムスケジュールでコンシューマクライアントに依存するのではなく、オフセットのコミットを処理します。