Search code examples
javamongodbapache-kafkajunit

Junit code for Kafka and Mongo standalone core java


I am having a core java application (standalone not springboot) to read a json message from Kafka topic, parse json, map source fields to target fields(field A in Kafka message might be field B in mongo collection) and write it to mongo collection. Everything works fine.

Now I want to write Junit test cases for Kafka, mongo and mapping classes.

In all the forums I am seeing samples with springboot and mockito. Please share any sample/references for core java code.


Solution

  • 1. Test Kafka

    For Kafka, you can use the EmbeddedKafka class from the spring-kafka-test library, even in a non-Spring Boot application:

    import org.apache.kafka.clients.producer.ProducerRecord;
    import org.apache.kafka.common.serialization.StringDeserializer;
    import org.apache.kafka.common.serialization.StringSerializer;
    import org.junit.jupiter.api.Test;
    import org.springframework.kafka.test.EmbeddedKafkaBroker;
    import org.springframework.kafka.test.context.EmbeddedKafka;
    import org.springframework.kafka.test.utils.KafkaTestUtils;
    
    import java.util.Map;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    @EmbeddedKafka(partitions = 1, topics = { "testTopic" })
    public class KafkaTest {
    
        @Test
        public void testKafka() {
            EmbeddedKafkaBroker embeddedKafka = new EmbeddedKafkaBroker(1, true, 1, "testTopic");
            embeddedKafka.afterPropertiesSet();
    
            Map<String, Object> producerProps = KafkaTestUtils.producerProps(embeddedKafka);
            ProducerRecord<String, String> record = new ProducerRecord<>("testTopic", "key", "value");
            KafkaTestUtils.getKafkaProducer(producerProps).send(record);
    
            Map<String, Object> consumerProps = KafkaTestUtils.consumerProps("testGroup", "true", embeddedKafka);
            ConsumerRecord<String, String> received = KafkaTestUtils.getSingleRecord(
                    KafkaTestUtils.getKafkaConsumer(consumerProps, new StringDeserializer(), new StringDeserializer()), "testTopic");
    
            assertEquals("value", received.value());
        }
    }
    
    1. Test MongoDB

    For MongoDB, you can use the Testcontainers library to spin up a MongoDB instance for testing

    import org.bson.Document;
    import org.junit.jupiter.api.AfterAll;
    import org.junit.jupiter.api.BeforeAll;
    import org.junit.jupiter.api.Test;
    import org.testcontainers.containers.MongoDBContainer;
    import com.mongodb.client.MongoClient;
    import com.mongodb.client.MongoClients;
    import com.mongodb.client.MongoCollection;
    import com.mongodb.client.MongoDatabase;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    public class MongoTest {
    
        private static MongoDBContainer mongoDBContainer;
        private static MongoClient mongoClient;
    
        @BeforeAll
        public static void setUp() {
            mongoDBContainer = new MongoDBContainer("mongo:4.4.3");
            mongoDBContainer.start();
            mongoClient = MongoClients.create(mongoDBContainer.getReplicaSetUrl());
        }
    
        @AfterAll
        public static void tearDown() {
            mongoClient.close();
            mongoDBContainer.stop();
        }
    
        @Test
        public void testMongo() {
            MongoDatabase database = mongoClient.getDatabase("test");
            MongoCollection<Document> collection = database.getCollection("testCollection");
    
            Document doc = new Document("name", "testName");
            collection.insertOne(doc);
    
            Document retrievedDoc = collection.find().first();
            assertEquals("testName", retrievedDoc.getString("name"));
        }
    }
    
    1. Test mapping classes

    For mapping classes, you can write simple unit tests using JUnit

    import org.junit.jupiter.api.Test;
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    public class MappingTest {
    
        @Test
        public void testMapping() {
            Source source = new Source("fieldAValue");
            Target target = new Target();
            target.setFieldB(source.getFieldA());
    
            assertEquals("fieldAValue", target.getFieldB());
        }
    
        class Source {
            private String fieldA;
    
            public Source(String fieldA) {
                this.fieldA = fieldA;
            }
    
            public String getFieldA() {
                return fieldA;
            }
        }
    
        class Target {
            private String fieldB;
    
            public void setFieldB(String fieldB) {
                this.fieldB = fieldB;
            }
    
            public String getFieldB() {
                return fieldB;
            }
        }
    }