X-Git-Url: https://juplo.de/gitweb/?a=blobdiff_plain;f=src%2Ftest%2Fjava%2Fde%2Fjuplo%2Fkafka%2Fwordcount%2Fcounter%2FCounterApplicationIT.java;h=78d103c282fbe7c4857220d6ca581cdc89264189;hb=e94a327bebf468e2bcb5b686346a18a1409ec254;hp=fd920006ed9811b60d5f868be2a90d1def1a1d6d;hpb=f8f9b6397ba0096bffa463e09a2db93277a3f9cf;p=demos%2Fkafka%2Fwordcount diff --git a/src/test/java/de/juplo/kafka/wordcount/counter/CounterApplicationIT.java b/src/test/java/de/juplo/kafka/wordcount/counter/CounterApplicationIT.java index fd92000..78d103c 100644 --- a/src/test/java/de/juplo/kafka/wordcount/counter/CounterApplicationIT.java +++ b/src/test/java/de/juplo/kafka/wordcount/counter/CounterApplicationIT.java @@ -1,11 +1,11 @@ package de.juplo.kafka.wordcount.counter; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; -import lombok.Value; import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.streams.KeyValue; import org.apache.kafka.streams.state.KeyValueBytesStoreSupplier; import org.apache.kafka.streams.state.Stores; import org.junit.jupiter.api.BeforeEach; @@ -16,16 +16,24 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.*; +import org.springframework.kafka.support.serializer.JsonDeserializer; +import org.springframework.kafka.support.serializer.JsonSerializer; import org.springframework.kafka.test.context.EmbeddedKafka; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; import java.time.Duration; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; import static de.juplo.kafka.wordcount.counter.CounterApplicationIT.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.*; +import static de.juplo.kafka.wordcount.counter.TestData.convertToMap; +import static de.juplo.kafka.wordcount.counter.TestData.parseHeader; +import static org.awaitility.Awaitility.await; +import static org.springframework.kafka.support.mapping.AbstractJavaTypeMapper.*; +import static org.springframework.kafka.support.mapping.AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME; @SpringBootTest( @@ -45,9 +53,7 @@ public class CounterApplicationIT static final int PARTITIONS = 2; @Autowired - KafkaTemplate kafkaTemplate; - @Autowired - ObjectMapper mapper; + KafkaTemplate kafkaTemplate; @Autowired Consumer consumer; @@ -60,95 +66,85 @@ public class CounterApplicationIT @Test - void testSendMessage() throws Exception + void testSendMessage() { - kafkaTemplate.send(TOPIC_IN, "peter", "Hallo"); - kafkaTemplate.send(TOPIC_IN, "klaus", "Müsch"); - kafkaTemplate.send(TOPIC_IN, "peter", "Welt"); - kafkaTemplate.send(TOPIC_IN, "klaus", "Müsch"); - kafkaTemplate.send(TOPIC_IN, "klaus", "s"); - kafkaTemplate.send(TOPIC_IN, "peter", "Boäh"); - kafkaTemplate.send(TOPIC_IN, "peter", "Welt"); - kafkaTemplate.send(TOPIC_IN, "peter", "Boäh"); - kafkaTemplate.send(TOPIC_IN, "klaus", "s"); - kafkaTemplate.send(TOPIC_IN, "peter", "Boäh"); - kafkaTemplate.send(TOPIC_IN, "klaus", "s"); - - Message peter1 = Message.of( - "{\"username\":\"peter\",\"word\":\"Hallo\"}", - "1"); - Message peter2 = Message.of( - "{\"username\":\"peter\",\"word\":\"Welt\"}", - "1"); - Message peter3 = Message.of( - "{\"username\":\"peter\",\"word\":\"Boäh\"}", - "1"); - Message peter4 = Message.of( - "{\"username\":\"peter\",\"word\":\"Welt\"}", - "2"); - Message peter5 = Message.of( - "{\"username\":\"peter\",\"word\":\"Boäh\"}", - "2"); - Message peter6 = Message.of( - "{\"username\":\"peter\",\"word\":\"Boäh\"}", - "3"); - - Message klaus1 = Message.of( - "{\"username\":\"klaus\",\"word\":\"Müsch\"}", - "1"); - Message klaus2 = Message.of( - "{\"username\":\"klaus\",\"word\":\"Müsch\"}", - "2"); - Message klaus3 = Message.of( - "{\"username\":\"klaus\",\"word\":\"s\"}", - "1"); - Message klaus4 = Message.of( - "{\"username\":\"klaus\",\"word\":\"s\"}", - "2"); - Message klaus5 = Message.of( - "{\"username\":\"klaus\",\"word\":\"s\"}", - "3"); + TestData.writeInputData((key, value) -> kafkaTemplate.send(TOPIC_IN, key, value)); await("Expexted converted data") .atMost(Duration.ofSeconds(10)) - .untilAsserted(() -> - { - assertThat(consumer.received).hasSize(2); - assertThat(consumer.received.get("klaus")).containsExactly(klaus1, klaus2, klaus3, klaus4, klaus5); - assertThat(consumer.received.get("peter")).containsExactly(peter1, peter2, peter3, peter4, peter5, peter6); - }); + .untilAsserted(() -> TestData.assertExpectedResult(consumer.getReceivedMessages())); } @RequiredArgsConstructor static class Consumer { - private final MultiValueMap received = new LinkedMultiValueMap<>(); - private final ObjectMapper mapper; + private final List> received = new LinkedList<>(); @KafkaListener(groupId = "TEST", topics = TOPIC_OUT) - public void receive(ConsumerRecord record) throws JsonProcessingException + public synchronized void receive(ConsumerRecord record) { - log.debug("Received message: {}", record); - Key key = mapper.readValue(record.key(), Key.class); - received.add(key.getUsername(), Message.of(record.key(),record.value())); + log.debug( + "Received message: {} -> {}, key: {}, value: {}", + record.key(), + record.value(), + parseHeader(record.headers(), KEY_DEFAULT_CLASSID_FIELD_NAME), + parseHeader(record.headers(), DEFAULT_CLASSID_FIELD_NAME)); + received.add(KeyValue.pair(record.key(),record.value())); } - } - @Value(staticConstructor = "of") - static class Message - { - String key; - String value; + synchronized List> getReceivedMessages() + { + return received; + } } @TestConfiguration static class Configuration { @Bean - Consumer consumer(ObjectMapper mapper) + ProducerFactory producerFactory(Properties streamProcessorProperties) + { + Map propertyMap = convertToMap(streamProcessorProperties); + + propertyMap.put( + ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, + JsonSerializer.class.getName()); + propertyMap.put( + ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, + JsonSerializer.class.getName()); + + return new DefaultKafkaProducerFactory<>(propertyMap); + } + + @Bean + ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory( + Properties streamProcessorProperties) + { + Map propertyMap = convertToMap(streamProcessorProperties); + + propertyMap.put( + ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, + JsonDeserializer.class.getName()); + propertyMap.put( + ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, + JsonDeserializer.class.getName()); + + ConsumerFactory consumerFactory = + new DefaultKafkaConsumerFactory<>(propertyMap); + + ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory = + new ConcurrentKafkaListenerContainerFactory<>(); + + kafkaListenerContainerFactory.setConsumerFactory(consumerFactory); + + return kafkaListenerContainerFactory; + } + + @Bean + Consumer consumer() { - return new Consumer(mapper); + return new Consumer(); } @Primary