When you create a Streams application, you create a Topology, either using the StreamsBuilder DSL
or using the low-level Processor API. Normally, you run the topology using the KafkaStreams class, which connects
to your broker and begins processing when you call start().
For testing, though, running a broker and making sure to clean up state between tests adds a lot of complexity and time.

Streams provides the TopologyTestDriver in the kafka-streams-test-utils package as a drop-in replacement for the KafkaStreams class.
It has no external system dependencies, and it also processes input synchronously, so you can verify the results immediately after providing input.
There are hooks for verifying data sent to output topics, and you can also query state stores maintained by your application under test.

The test driver accepts ConsumerRecords with key and value type byte[].
Because byte[] types can be problematic, you can use the ConsumerRecordFactory
to generate records by providing regular Java types for key and values and the corresponding serializers.

ProducerRecord contains all the record metadata in addition to the key and value, which can make it awkward to use with test frameworks' equality checks.
Instead, consider using the OutputVerifier methods to compare just some parts of the records.

// throws AssertionError if key or value does not matchOutputVerifier.compareKeyValue(outputRecord,"key",42L);

TopologyTestDriver supports punctuations, too.
Event-time punctuations are triggered automatically based on the processed records' timestamps.
Wall-clock-time punctuations can also be triggered by advancing the test driver's wall-clock time.
The driver's wall-clock time must be advanced manually (this is for test stability).

testDriver.advanceWallClockTime(20L);// supposing that a scheduled punctuator would emit this record...ProducerRecord<String,Integer>outputRecord=testDriver.readOutput("output-topic",newStringDeserializer(),newStringDeserializer());OutputVerifier.compareKeyValue(outputRecord,"triggered-key","triggered-value");

Additionally, state stores are accessible via the test driver before or after a test.
Accessing stores before a test is useful to pre-populate a store with some initial values.
After data was processed, expected updates to the store can be verified.

The following example demonstrates how to use the test driver and helper classes. The example creates a topology that computes the maximum value per key using a key-value-store. While processing, no output is generated, but only the store is updated. Output is only sent downstream based on event-time and wall-clock punctuations.

The mock captures any values that your processor forwards. You can make assertions on them:

processorUnderTest.process("key","value");finalIterator<CapturedForward>forwarded=context.forwarded().iterator();assertEquals(forwarded.next().keyValue(),newKeyValue<>(...,...));assertFalse(forwarded.hasNext());// you can reset forwards to clear the captured data. This may be helpful in constructing longer scenarios.context.resetForwards();assertEquals(context.forwarded().size(),0);

If your processor forwards to specific child processors, you can query the context for captured data by child name:

Once these are set, the context continues returning the same values, until you set new ones.

In case your punctuator is stateful, the mock context allows you to register state stores.
You are encouraged to use a simple in-memory store of the appropriate type (KeyValue, Windowed, or Session),
since the mock context does not manage changelogs, state directories, etc.

finalKeyValueStore<String,Integer>store=Stores.keyValueStoreBuilder(Stores.inMemoryKeyValueStore("myStore"),Serdes.String(),Serdes.Integer()).withLoggingDisabled()// Changelog is not supported by MockProcessorContext..build();store.init(context,store);context.register(store,/*parameter unused in mock*/null);

Processors can schedule punctuators to handle periodic tasks.
The mock context does not automatically execute punctuators, but it does capture
schedule calls so that you can unit test the punctuator scheduling behavior yourself: