Testing Kafka Applications
1. Using EmbeddedKafka
| Aspect | Description | Detail |
|---|---|---|
| In-Process | Broker in JVM | No external |
| JUnit Ext | Spring Kafka Test | Annotation |
| Testcontainers | Real broker in Docker | Alternative |
Example: EmbeddedKafka
@EmbeddedKafka(partitions = 1, topics = {"orders"})
@SpringBootTest
class OrderTest { /* broker auto-started */ }
2. Creating Test Producer
| Aspect | Description | Detail |
|---|---|---|
| Embedded Brokers | Point to test addr | spring.embedded |
| Sync Send | get() for determinism | Assert |
| Cleanup | Close after test | Resource |
Example: Test producer
var props = KafkaTestUtils.producerProps(embeddedKafka);
var producer = new KafkaProducer<String,String>(props,
new StringSerializer(), new StringSerializer());
producer.send(new ProducerRecord<>("orders","k","v")).get();
3. Creating Test Consumer
| Aspect | Description | Detail |
|---|---|---|
| earliest | Read from start | auto.offset.reset |
| getRecords | Poll helper | KafkaTestUtils |
| Assert | Verify content | Equals |
Example: Test consumer
var props = KafkaTestUtils.consumerProps("grp","true",embeddedKafka);
var c = new KafkaConsumer<String,String>(props);
c.subscribe(List.of("orders"));
var rec = KafkaTestUtils.getSingleRecord(c, "orders");
assertEquals("v", rec.value());
4. Testing Streams Topology
| Aspect | Description | Detail |
|---|---|---|
| TopologyTestDriver | No broker needed | Fast |
| TestInputTopic | Pipe records in | Feed |
| TestOutputTopic | Read results | Assert |
Example: TopologyTestDriver
var driver = new TopologyTestDriver(topology, props);
var in = driver.createInputTopic("in", ks, vs);
var out = driver.createOutputTopic("out", kd, vd);
in.pipeInput("k", "v");
assertEquals("V", out.readValue());
5. Mocking External Dependencies
| Aspect | Description | Detail |
|---|---|---|
| MockProducer | In-memory producer | No broker |
| MockConsumer | Scripted records | addRecord |
| Mockito | Stub collaborators | Isolation |
Example: MockProducer
var mock = new MockProducer<>(true,
new StringSerializer(), new StringSerializer());
service.publish(mock, "k", "v");
assertEquals(1, mock.history().size());
6. Testing Serialization
| Aspect | Description | Detail |
|---|---|---|
| Round-Trip | serialize then deserialize | Equality |
| Schema Compat | Old reads new | Evolution |
| Null Handling | Tombstones | Edge case |
Example: Serde round-trip
byte[] bytes = serde.serializer().serialize("t", obj);
Order back = serde.deserializer().deserialize("t", bytes);
assertEquals(obj, back);
7. Testing Error Scenarios
| Scenario | Description | Detail |
|---|---|---|
| Send Failure | MockProducer errorNext | Inject |
| Deserialize Error | Poison pill | Bad bytes |
| Retry/DLQ | Verify handling | Path |
Example: Inject send error
var mock = new MockProducer<>(false, ks, vs);
var f = service.publish(mock, "k", "v");
mock.errorNext(new RuntimeException("broker down"));
assertThrows(ExecutionException.class, f::get);
8. Integration Testing
| Aspect | Description | Detail |
|---|---|---|
| Testcontainers | Real Kafka in Docker | Realistic |
| End-to-End | Produce → process → consume | Full flow |
| Awaitility | Async assertions | Poll-wait |
Example: KafkaContainer
@Container
static KafkaContainer kafka =
new KafkaContainer(DockerImageName.parse("apache/kafka:3.9.0"));
// kafka.getBootstrapServers() for clients
9. Performance Testing
| Tool | Description | Detail |
|---|---|---|
| producer-perf-test | Throughput/latency | Built-in |
| consumer-perf-test | Consume rate | Built-in |
| Trogdor | Fault + load harness | Advanced |
Example: Producer perf test
kafka-producer-perf-test.sh --topic perf --num-records 1000000 \
--record-size 1024 --throughput -1 \
--producer-props bootstrap.servers=localhost:9092
10. Load Testing
| Aspect | Description | Detail |
|---|---|---|
| Sustained Load | Hold target rate | Soak |
| Ramp-Up | Gradual increase | Find limit |
| Monitor Lag | Watch under load | SLO check |