Source:
public void shouldEnqueueLaterOutputsAfterEarlierOnes() { final Properties properties = new Properties(); properties.setProperty(StreamsConfig.APPLICATION_ID_CONFIG, "dummy"); properties.setProperty(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "dummy"); final Topology topology = new Topology(); topology.addSource("source", new StringDeserializer(), new StringDeserializer(), "input"); topology.addProcessor( "recursiveProcessor", () -> new AbstractProcessor<String, String>() { @Override public void process(final String key, final String value) { if (!value.startsWith("recurse-")) { context().forward(key, "recurse-" + value, To.child("recursiveSink")); } context().forward(key, value, To.child("sink")); } }, "source" ); topology.addSink("recursiveSink", "input", new StringSerializer(), new StringSerializer(), "recursiveProcessor"); topology.addSink("sink", "output", new StringSerializer(), new StringSerializer(), "recursiveProcessor"); try (final TopologyTestDriver topologyTestDriver = new TopologyTestDriver(topology, properties)) { final TestInputTopic<String, String> in = topologyTestDriver.createInputTopic("input", new StringSerializer(), new StringSerializer()); final TestOutputTopic<String, String> out = topologyTestDriver.createOutputTopic("output", new StringDeserializer(), new StringDeserializer()); in.pipeInput("A", "alpha"); final Map<String, String> table = out.readKeyValuesToMap(); assertThat(table, is(Collections.singletonMap("A", "recurse-alpha"))); in.pipeInput("B", "beta"); final List<KeyValue<String, String>> events = out.readKeyValuesToList(); assertThat( events, is(Arrays.asList( new KeyValue<>("B", "beta"), new KeyValue<>("B", "recurse-beta") )) ); } }

Target:
public void shouldEnqueueLaterOutputsAfterEarlierOnes() { final Properties properties = new Properties(); properties.setProperty(StreamsConfig.APPLICATION_ID_CONFIG, "dummy"); properties.setProperty(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "dummy"); final Topology topology = new Topology(); topology.addSource("source", new StringDeserializer(), new StringDeserializer(), "input"); topology.addProcessor( "recursiveProcessor", () -> new AbstractProcessor<String, String>() { @Override public void process(final String key, final String value) { if (!value.startsWith("recurse-")) { context().forward(key, "recurse-" + value, To.child("recursiveSink")); } context().forward(key, value, To.child("sink")); } }, "source" ); topology.addSink("recursiveSink", "input", new StringSerializer(), new StringSerializer(), "recursiveProcessor"); topology.addSink("sink", "output", new StringSerializer(), new StringSerializer(), "recursiveProcessor"); try (final TopologyTestDriver topologyTestDriver = new TopologyTestDriver(topology, properties)) { final TestInputTopic<String, String> in = topologyTestDriver.createInputTopic("input", new StringSerializer(), new StringSerializer()); final TestOutputTopic<String, String> out = topologyTestDriver.createOutputTopic("output", new StringDeserializer(), new StringDeserializer()); in.pipeInput("B", "beta"); final List<KeyValue<String, String>> events = out.readKeyValuesToList(); assertThat( events, is(Arrays.asList( new KeyValue<>("B", "beta"), new KeyValue<>("B", "recurse-beta") )) ); } }