DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
World desk6 min

How to Test a Kafka Streams Topology Without Running Kafka

Kafka's TopologyTestDriver runs Kafka Streams topology logic in a plain test process, with no broker. Here is how to set it up, handle event-time and wall-clock punctuation, inspect state, and know where its single-partition model stops matching a real cluster.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You can exercise Kafka Streams topology logic inside a plain test process, with no broker, no cluster, and no deployment. Kafka’s TopologyTestDriver feeds records through your topology, captures the output, and lets you inspect state stores. It answers “does this logic produce the right results for these inputs?” It does not answer “how does this behave on a real cluster?” Keeping those two questions separate is the difference between a fast, reliable test suite and a false sense of safety.

What the driver does and does not replace

Apache Kafka’s TopologyTestDriver API documentation describes the class this way: “Best of all, the class works without a real Kafka broker, so the tests execute very quickly with very little overhead.” The driver can test a topology assembled either with the low-level Topology class or with the DSL’s StreamsBuilder. Internally it simulates Kafka consumers and producers, and its test input and output helpers convert ordinary Java objects to and from serialized bytes.

As an Amazon Associate I earn from qualifying purchases.

That makes it a strong tool for unit-level and topology-level verification: filters, joins, aggregations, custom Processor API logic, and state-dependent branching. It is a weak tool for anything that depends on how Kafka actually moves data. Use a broker-backed integration test when the question involves real cluster behavior, multiple partitions, deployment configuration, or interaction with brokers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choosing the right test type

Question you need answered TopologyTestDriver Broker-backed integration test
Does the topology transform and route records correctly? Yes, quickly and deterministically Yes, but slower to run
Does a real Kafka broker need to be running? No Yes
Is partition-sensitive or multi-partition behavior being tested? No. Input topics are simulated as single-partitioned Yes, when the test creates multi-partition topics
Are deployment settings and broker configuration under test? Not really. Only the configuration you pass to the driver applies Yes
Can state stores be read and pre-populated directly? Yes Possible, but usually indirect
Can event-time and wall-clock punctuation be controlled? Yes, through record timestamps and an explicit mock wall clock Only with real or approximated timing

The practical rule: run driver tests on every build, and keep a smaller set of broker-backed tests for the behaviors the driver cannot model.

Dependency setup

Add the kafka-streams-test-utils artifact as a test-scoped dependency. The Apache Kafka 3.8 documentation for Streams testing shows this pattern. Match the artifact version to the Kafka Streams version your application already uses. Do not copy an example version from a guide without checking it against your build.

<dependency>
  <groupId>org.apache.kafka</groupId>
  <artifactId>kafka-streams-test-utils</artifactId>
  <version>${kafka.version}</version>
  <scope>test</scope>
</dependency>

Define kafka.version once in your parent POM or version catalog, so the production Streams client and the test utilities cannot drift apart.

Writing a driver test, step by step

  1. Build the topology. With the DSL, construct it with StreamsBuilder and call build(). With the Processor API, assemble the Topology directly. Either form works with the driver.
  2. Create the driver with representative configuration. Pass a Properties object that includes at least an application ID, a bootstrap servers value (it is not contacted), and the default key and value serdes your topology relies on. If your logic reads timestamps, set the timestamp extractor too, using StreamsConfig.DEFAULT_TIMESTAMP_EXTRACTOR_CLASS_CONFIG. A driver built with missing serde settings can fail in ways that look like topology bugs.
  3. Create input and output helpers. Call createInputTopic with the topic name and serializers, and createOutputTopic with the topic name and deserializers. The helper types are TestInputTopic<K, V> and TestOutputTopic<K, V>.
  4. Pipe input and assert output. Call pipeInput on the input helper, then read results with readValue, readKeyValue, or readRecordsToList on the output helper.
  5. Close the driver. Release it in a finally block or test teardown so resources are freed even when an assertion fails.
Topology topology = builder.build();
Properties props = new Properties();
props.put(StreamsConfig.APPLICATION_ID_CONFIG, "orders-test");
props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "unused:9092");
props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());

TopologyTestDriver driver = new TopologyTestDriver(topology, props);
try {
    TestInputTopic<String, String> in = driver.createInputTopic(
        "orders", new StringSerializer(), new StringSerializer());
    TestOutputTopic<String, String> out = driver.createOutputTopic(
        "enriched", new StringDeserializer(), new StringDeserializer());

    in.pipeInput("order-1", "widget");
    assertEquals("widget-enriched", out.readValue());
} finally {
    driver.close();
}

The bootstrap address is never contacted. Any well-formed value works, but writing an obviously fake one makes it clear to future readers that no broker is involved.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Testing time-based logic

Time handling is where driver tests most often go wrong, because there are two different clocks.

Event-time punctuation

Calling pipeInput can trigger event-time punctuation. The driver advances stream time as records arrive, so you control progress by setting record timestamps. Supply timestamps that cross your punctuation interval, and the scheduled callback fires as it would in a running application. Verify the emitted results after the input that should trigger the callback.

Wall-clock punctuation

Wall-clock punctuation does not follow record timestamps. It requires you to advance the driver’s mocked wall-clock time explicitly, using advanceWallClockTime with a Duration. Until you do, a wall-clock schedule will not fire, which can look like a broken topology when the real cause is a test that never moved the clock.

Rank #4
Metamorphosis: Franz Kafka (Little Clothbound Classics)
  • Metamorphosis: Franz Kafka (Little Clothbound Classics)

Inspecting and pre-populating state stores

The driver exposes the topology’s state stores, so you can check what a processor wrote and seed state before input is piped. Use getKeyValueStore or getWindowStore with the store name your topology declared. Seeding is useful when a test needs an existing aggregate or lookup row to exist before the first record arrives, and it avoids building a long warm-up sequence of inputs just to reach that state.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Limits that change what your tests prove

Input is processed synchronously

The current API documentation states that input processing is synchronous. The configuration settings commit.interval.ms and cache.max.bytes.buffering have no effect in the driver. Behavior is as if each input is committed and flushed immediately. A test cannot reproduce the timing of batched commits or cache-driven flushes, so a bug that appears only under those conditions will not appear in a driver test.

Input topics are single-partitioned

Every input topic is simulated as a single partition. Any logic that depends on key distribution across partitions, co-partitioning of joined topics, or ordering behavior among multiple partitions needs a broker-backed test. Do not present a passing driver test as evidence that those behaviors are correct.

Driver tests assume your configuration is representative

The driver uses only the properties you give it. If production sets timestamp extractors, serdes, or state directory options differently, the test passes against a configuration that does not exist in production. Keep the test properties drawn from the same source as the application’s real configuration wherever practical.

Keeping the test and the application on the same version

Apache Kafka’s API reference is published for the current release line, and at the time of this review its reference was for Kafka 4.3.1. The Streams testing guide in the Kafka 3.8 documentation points readers to the latest documentation for current details. Treat both as references, and confirm class names and method signatures against the exact version your project compiles against. If your application runs on an older Kafka Streams release, the method names above should be checked in that version’s Javadoc before you rely on them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A quick verification before writing a large suite: create a one-operator topology, run one record through the driver, and confirm the output. That single test exposes most setup problems, including missing serdes and a mismatched test-utils version, before they multiply across the suite.

“

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.