defaultSerde())
110 | .expectNextRecord().hasKey(new City("City1", 2)).hasValue(new Person("Huey", "City1"))
111 | .expectNoMoreRecord();
112 | }
113 |
114 | @Test
115 | void shouldVerifyNullKeys() {
116 | this.testTopology.input()
117 | .add(null, new City("City1", 2));
118 |
119 | this.testTopology.streamOutput()
120 | .expectNextRecord().hasKey(null).hasValue(new City("City1", 2))
121 | .expectNoMoreRecord();
122 | }
123 |
124 | @Test
125 | void shouldVerifyNullValues() {
126 | this.testTopology.input()
127 | .add(new Person("Huey", "City1"), null);
128 |
129 | this.testTopology.streamOutput()
130 | .expectNextRecord().hasKey(new Person("Huey", "City1")).hasValue(null)
131 | .expectNoMoreRecord();
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests-junit5/src/main/java/com/bakdata/fluent_kafka_streams_tests/junit5/TestTopologyExtension.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2025 bakdata
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.bakdata.fluent_kafka_streams_tests.junit5;
26 |
27 | import com.bakdata.fluent_kafka_streams_tests.TestTopology;
28 | import java.util.Map;
29 | import java.util.function.Function;
30 | import java.util.function.Supplier;
31 | import lombok.Getter;
32 | import org.apache.kafka.common.serialization.Serde;
33 | import org.apache.kafka.streams.Topology;
34 | import org.junit.jupiter.api.extension.AfterEachCallback;
35 | import org.junit.jupiter.api.extension.BeforeEachCallback;
36 | import org.junit.jupiter.api.extension.ExtensionContext;
37 |
38 | /**
39 | * Represents the main interaction with Kafka for testing purposes. Handles all inputs and outputs of the
40 | * {@link Topology} under test. This should be registered as an extension in your JUnit tests, to ensure that certain
41 | * setup and teardown methods are called.
Usage:
42 | *
43 | * class WordCountTest {
44 | * private final WordCount app = new WordCount();
45 | *
46 | * {@literal @RegisterExtension
47 | * final TestTopologyExtension
65 | * With {@code app} being any Kafka Streams application that you want to test.
66 | * @param Default type of keys
67 | * @param Default type of values
68 | */
69 | @Getter
70 | public class TestTopologyExtension extends TestTopology
71 | implements BeforeEachCallback, AfterEachCallback {
72 |
73 | public TestTopologyExtension(
74 | final Function super Map, ? extends Topology> topologyFactory,
75 | final Map properties) {
76 | super(topologyFactory, properties);
77 | }
78 |
79 | public TestTopologyExtension(
80 | final Supplier extends Topology> topologyFactory, final Map properties) {
81 | super(topologyFactory, properties);
82 | }
83 |
84 | public TestTopologyExtension(final Topology topology, final Map properties) {
85 | super(topology, properties);
86 | }
87 |
88 | protected TestTopologyExtension(
89 | final Function super Map, ? extends Topology> topologyFactory,
90 | final Map userProperties,
91 | final Serde defaultKeySerde, final Serde defaultValueSerde) {
92 | super(topologyFactory, userProperties, defaultKeySerde, defaultValueSerde);
93 | }
94 |
95 | @Override
96 | public void afterEach(final ExtensionContext context) {
97 | this.stop();
98 | }
99 |
100 | @Override
101 | public void beforeEach(final ExtensionContext context) {
102 | this.start();
103 | }
104 |
105 | @Override
106 | public TestTopologyExtension withDefaultValueSerde(final Serde defaultValueSerde) {
107 | return (TestTopologyExtension) super.withDefaultValueSerde(defaultValueSerde);
108 | }
109 |
110 | @Override
111 | public TestTopologyExtension withDefaultKeySerde(final Serde defaultKeySerde) {
112 | return (TestTopologyExtension) super.withDefaultKeySerde(defaultKeySerde);
113 | }
114 |
115 | @Override
116 | public TestTopologyExtension withDefaultSerde(final Serde defaultKeySerde,
117 | final Serde defaultValueSerde) {
118 | return (TestTopologyExtension) super.withDefaultSerde(defaultKeySerde, defaultValueSerde);
119 | }
120 |
121 | @Override
122 | protected TestTopology with(
123 | final Function super Map, ? extends Topology> topologyFactory,
124 | final Map userProperties, final Serde defaultKeySerde,
125 | final Serde defaultValueSerde) {
126 | return new TestTopologyExtension<>(topologyFactory, userProperties, defaultKeySerde, defaultValueSerde);
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests-junit4/src/main/java/com/bakdata/fluent_kafka_streams_tests/junit4/TestTopologyRule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2025 bakdata
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.bakdata.fluent_kafka_streams_tests.junit4;
26 |
27 | import com.bakdata.fluent_kafka_streams_tests.TestTopology;
28 | import java.util.Map;
29 | import java.util.function.Function;
30 | import java.util.function.Supplier;
31 | import lombok.Getter;
32 | import org.apache.kafka.common.serialization.Serde;
33 | import org.apache.kafka.streams.Topology;
34 | import org.junit.rules.TestRule;
35 | import org.junit.runner.Description;
36 | import org.junit.runners.model.Statement;
37 |
38 | /**
39 | * Represents the main interaction with Kafka for testing purposes. Handles all inputs and outputs of the
40 | * {@link Topology} under test. This should be registered as an extension in your JUnit tests, to ensure that certain
41 | * setup and teardown methods are called.
Usage:
42 | *
43 | * public class WordCountTest {
44 | * private final WordCount app = new WordCount();
45 | *
46 | * {@literal @Rule
47 | * public final TestTopologyRule
65 | * With {@code app} being any Kafka Streams application that you want to test.
66 | * @param Default type of keys
67 | * @param Default type of values
68 | */
69 | @Getter
70 | public class TestTopologyRule extends TestTopology
71 | implements TestRule {
72 | public TestTopologyRule(
73 | final Function super Map, ? extends Topology> topologyFactory,
74 | final Map properties) {
75 | super(topologyFactory, properties);
76 | }
77 |
78 | public TestTopologyRule(
79 | final Supplier extends Topology> topologyFactory, final Map properties) {
80 | super(topologyFactory, properties);
81 | }
82 |
83 | public TestTopologyRule(final Topology topology, final Map properties) {
84 | super(topology, properties);
85 | }
86 |
87 | protected TestTopologyRule(
88 | final Function super Map, ? extends Topology> topologyFactory,
89 | final Map userProperties,
90 | final Serde defaultKeySerde, final Serde defaultValueSerde) {
91 | super(topologyFactory, userProperties, defaultKeySerde, defaultValueSerde);
92 | }
93 |
94 | @Override
95 | public Statement apply(final Statement base, final Description description) {
96 | return new Statement() {
97 | @Override
98 | public void evaluate() throws Throwable {
99 | TestTopologyRule.this.start();
100 | try {
101 | base.evaluate();
102 | } finally {
103 | TestTopologyRule.this.stop();
104 | }
105 | }
106 | };
107 | }
108 |
109 | @Override
110 | public TestTopologyRule withDefaultValueSerde(final Serde defaultValueSerde) {
111 | return (TestTopologyRule) super.withDefaultValueSerde(defaultValueSerde);
112 | }
113 |
114 | @Override
115 | public TestTopologyRule withDefaultKeySerde(final Serde defaultKeySerde) {
116 | return (TestTopologyRule