Kafka Streams
Functional Testing
Avro
Schema Registry
Software Development

How can do Functional tests for Kafka Streams with Avro (schemaRegistry)?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Apache Kafka Streams is a powerful tool for building real-time streaming applications that can process incoming data feeds and provide insights immediately. Testing such applications, particularly when they use complex data structures propagated through Avro formats, is not just essential—it’s critical for ensuring the accuracy and reliability of streaming data applications.

Importance of Testing Kafka Streams with Avro

Apache Avro is a popular serialization framework used in conjunction with Kafka, particularly because of its schema evolution capabilities, which are critical in systems handling evolving data structures. Kafka Streams, designed to build complex transformations and process an unbounded stream of data from Kafka, often depends on data formatted in Avro. The Schema Registry maintains a store of Avro schemas used by Kafka topics, which helps ensure compatibility between producers and consumers by enforcing data structure agreements.

Setting Up the Testing Environment

The foundation for functionally testing Kafka Streams applications involves setting up a testing environment that mimics production scenarios as closely as possible. Key components include:

  1. Embedded Kafka Cluster: Including Kafka Brokers and Zookeeper.
  2. Mock Schema Registry: To handle Avro schema registrations and validations.
  3. Test Data Producers and Consumers: To create scenarios and validate the outcomes of Kafka Streams applications.

Tool and Libraries

Several libraries are critical for effectively testing Kafka Streams with Avro:

  • Testcontainers: For spinning up Docker containers of Kafka and Schema Registry.
  • Confluent's Kafka and Schema Registry Clients: To interact with Kafka and the schema registry during tests.
  • Spring Kafka Test: If you’re using Spring, this can provide some helpful integrations.

Writing the Test

Initializing Containers

Using Testcontainers, initialize the Kafka and Schema Registry containers:

java
1public class KafkaStreamsTest {
2    private static KafkaContainer kafkaContainer;
3    private static SchemaRegistryContainer schemaRegistryContainer;
4
5    @BeforeAll
6    public static void setup() {
7        kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"));
8        kafkaContainer.start();
9        
10        schemaRegistryContainer = new SchemaRegistryContainer(kafkaContainer.getNetwork());
11        schemaRegistryContainer.start();
12    }
13
14    @AfterAll
15    public static void tearDown() {
16        kafkaContainer.stop();
17        schemaRegistryContainer.stop();
18    }
19}

Configuring Kafka Streams

Configure Kafka Streams to point at the test Kafka and Schema Registry endpoints:

java
1Properties properties = new Properties();
2properties.put(StreamsConfig.APPLICATION_ID_CONFIG, "test-app");
3properties.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaContainer.getBootstrapServers());
4properties.put(AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, schemaRegistryContainer.getUrl());

Producing Test Data

Producing test data involves creating Avro objects, serializing them, and sending them to Kafka:

java
1Producer<String, GenericRecord> producer = createAvroProducer(kafkaContainer.getBootstrapServers(), schemaRegistryContainer.getUrl());
2GenericRecord record = new GenericData.Record(schema);
3record.put("field1", "value1");
4producer.send(new ProducerRecord<>("topic", recordKey, record));
5producer.close();

Implementing and Testing the Stream Processor

Once a stream is defined, write tests to verify its behavior:

java
1KafkaStreams streams = new KafkaStreams(streamsBuilder.build(), properties);
2streams.start();
3
4// Test logic here to verify the transformations or processed results

Best Practices

  1. Thoroughly test all error scenarios: This includes schema compatibility issues.
  2. Use different sets of data: representing both typical and boundary cases.
  3. Integrate Continuous Integration (CI): Automate tests to run with every build.

Summary

Here’s a table summarizing key points:

ComponentResponsibilityTools/Technologies Utilized
Embedded Kafka ClusterMimics the actual Kafka environmentKafka, Zookeeper, Testcontainers
Mock Schema RegistryEnforces Avro schema validation and compatibilitySchema Registry, Testcontainers
Test Producers/ConsumersProduce scenarios and validate outcomes of stream processorKafka Clients, Avro

By following the outlined steps and best practices, you can ensure your Kafka Streams applications process real-time data streams efficiently and accurately, even as data schemas evolve.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.