and() {
115 | return this;
116 | }
117 |
118 | /**
119 | * Reads the next record and creates an {@code Expectation} for it.
120 | * This is logically equivalent to {@link TestOutput#expectNextRecord()}.
121 | * This methods main purpose is to allow chaining:
122 | * {@code
123 | * myOutput.expectNextRecord()
124 | * .expectNextRecord()
125 | * .expectNoMoreRecord();
126 | * }
127 | *
128 | * @return An {@code Expectation} containing the next record from the output.
129 | */
130 | public Expectation expectNextRecord() {
131 | return this.output.expectNextRecord();
132 | }
133 |
134 | /**
135 | * Reads the next record from the output and expects it to be the end of output.
136 | * This is logically equivalent to {@link TestOutput#expectNoMoreRecord()}.
137 | * This methods main purpose is to allow chaining:
138 | * {@code
139 | * myOutput.expectNextRecord()
140 | * .expectNextRecord()
141 | * .expectNoMoreRecord();
142 | * }
143 | *
144 | * @return An {@code Expectation} containing the next record from the output.
145 | */
146 | public Expectation expectNoMoreRecord() {
147 | return this.output.expectNoMoreRecord();
148 | }
149 |
150 | /**
151 | * Asserts that there is no records present, i.e., the end of the output has been reached.
152 | * This method should be used when there are no records at all expected.
153 | * @return the current {@code Expectation} chain
154 | */
155 | public Expectation toBeEmpty() {
156 | if (this.lastRecord != null) {
157 | throw new AssertionError(
158 | String.format("More records found. {key='%s', value='%s'}", this.lastRecord.key(), this.lastRecord.value()));
159 | }
160 | return this.and();
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests/src/main/java/com/bakdata/fluent_kafka_streams_tests/StreamOutput.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;
26 |
27 | import com.bakdata.kafka.Configurator;
28 | import java.util.Iterator;
29 | import java.util.NoSuchElementException;
30 | import lombok.NonNull;
31 | import org.apache.kafka.clients.producer.ProducerRecord;
32 | import org.apache.kafka.common.serialization.Serde;
33 | import org.apache.kafka.streams.TopologyTestDriver;
34 |
35 | /**
36 | * Represents the {@link TestOutput} with {@link org.apache.kafka.streams.kstream.KStream} semantics.
37 | *
38 | * Note: The StreamOutput is a one-time iterable. Cache it if you need to iterate several times.
39 | */
40 | class StreamOutput extends BaseOutput {
41 | StreamOutput(final TopologyTestDriver testDriver, final String topic, final Serde keySerde,
42 | final Serde valueSerde, final Configurator configurator) {
43 | super(testDriver, topic, keySerde, valueSerde, configurator);
44 | }
45 |
46 | /**
47 | * Reads the next value from the output stream.
Usually, you should not need to call this. The recommended way
48 | * should be to use either
49 | *
50 | * - the {@link #expectNextRecord()} and {@link #expectNoMoreRecord()} methods OR
51 | * - the iterable interface (via {@link #iterator()}.
52 | *
53 | *
54 | * @return The next value in the output stream. {@code null} if no more values are present.
55 | */
56 | @Override
57 | public ProducerRecord readOneRecord() {
58 | return this.readFromTestDriver();
59 | }
60 |
61 | /**
62 | * Creates an iterator of {@link ProducerRecord} for the stream output. Can only be read once.
63 | */
64 | @Override
65 | public @NonNull Iterator> iterator() {
66 | return new Iterator>() {
67 | private ProducerRecord current = StreamOutput.this.readFromTestDriver();
68 |
69 | @Override
70 | public boolean hasNext() {
71 | return this.current != null;
72 | }
73 |
74 | @Override
75 | public ProducerRecord next() {
76 | if (!this.hasNext()) {
77 | throw new NoSuchElementException();
78 | }
79 | final ProducerRecord toReturn = this.current;
80 | this.current = StreamOutput.this.readFromTestDriver();
81 | return toReturn;
82 | }
83 | };
84 | }
85 |
86 | // ==================
87 | // Non-public methods
88 | // ==================
89 | @Override
90 | protected TestOutput create(final TopologyTestDriver testDriver, final String topic,
91 | final Serde keySerde, final Serde valueSerde, final Configurator configurator) {
92 | return new StreamOutput<>(testDriver, topic, keySerde, valueSerde, configurator);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests/src/main/java/com/bakdata/fluent_kafka_streams_tests/TableOutput.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;
26 |
27 | import com.bakdata.kafka.Configurator;
28 | import java.util.Iterator;
29 | import java.util.LinkedHashMap;
30 | import java.util.Map;
31 | import lombok.NonNull;
32 | import org.apache.kafka.clients.producer.ProducerRecord;
33 | import org.apache.kafka.common.serialization.Serde;
34 | import org.apache.kafka.streams.TopologyTestDriver;
35 |
36 | class TableOutput extends BaseOutput {
37 | private final Map> table = new LinkedHashMap<>();
38 | private Iterator> tableIterator;
39 |
40 | TableOutput(final TopologyTestDriver testDriver, final String topic, final Serde keySerde,
41 | final Serde valueSerde, final Configurator configurator) {
42 | super(testDriver, topic, keySerde, valueSerde, configurator);
43 | }
44 |
45 | /**
46 | * Reads the next value from the output stream.
47 | * Usually, you should not need to call this. The recommended way should be to use either
48 | *
49 | * - the {@link #expectNextRecord()} and {@link #expectNoMoreRecord()} methods OR
50 | * - the iterable interface (via {@link #iterator()}.
51 | *
52 | *
53 | * @return The next value in the output stream. {@code null} if no more values are present.
54 | */
55 | @Override
56 | public ProducerRecord readOneRecord() {
57 | if (this.tableIterator == null) {
58 | this.tableIterator = this.iterator();
59 | }
60 |
61 | // Emulate testDriver, which returns null on last read
62 | return this.tableIterator.hasNext() ? this.tableIterator.next() : null;
63 | }
64 |
65 | /**
66 | * Creates an iterator of {@link ProducerRecord} for the table output. Can only be read once.
67 | */
68 | @Override
69 | public @NonNull Iterator> iterator() {
70 | ProducerRecord producerRecord = this.readFromTestDriver();
71 | while (producerRecord != null) {
72 | this.table.put(producerRecord.key(), producerRecord);
73 | producerRecord = this.readFromTestDriver();
74 | }
75 | return this.table.values().stream().iterator();
76 | }
77 |
78 | // ==================
79 | // Non-public methods
80 | // ==================
81 | @Override
82 | protected TestOutput create(final TopologyTestDriver testDriver, final String topic,
83 | final Serde keySerde, final Serde valueSerde, final Configurator configurator) {
84 | return new TableOutput<>(testDriver, topic, keySerde, valueSerde, configurator);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests/src/main/java/com/bakdata/fluent_kafka_streams_tests/TestOutput.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;
26 |
27 | import com.bakdata.kafka.Preconfigured;
28 | import java.util.List;
29 | import org.apache.kafka.clients.producer.ProducerRecord;
30 | import org.apache.kafka.common.serialization.Serde;
31 |
32 |
33 | /**
34 | * Represents the output stream of the tested app via the {@link TestTopology}.
35 | * This can be used via the {@link StreamOutput} or the {@link TableOutput}, dependent on the desired semantics.
36 | * For more details see each implementation.
37 | *
38 | * Note: The StreamOutput is a one-time iterable. Cache it if you need to iterate several times.
39 | *
40 | * @param the key type of the output stream
41 | * @param the value type of the output stream
42 | */
43 | public interface TestOutput extends Iterable> {
44 | /**
45 | * Set new serde for this output.
46 | *
47 | * @param keySerde The serializer/deserializer to be used for the keys in the output
48 | * @param valueSerde The serializer/deserializer to be used for the values in the output
49 | * @return Copy of current {@code TestOutput} with provided serdes
50 | */
51 | TestOutput withSerde(Serde keySerde, Serde valueSerde);
52 |
53 | /**
54 | * Set new serde for this output. Serdes are configured using properties of the test topology.
55 | *
56 | * @param keySerde The serializer/deserializer to be used for the keys in the output
57 | * @param valueSerde The serializer/deserializer to be used for the values in the output
58 | * @return Copy of current {@code TestOutput} with provided serdes
59 | */
60 | TestOutput configureWithSerde(Preconfigured extends Serde> keySerde,
61 | Preconfigured extends Serde> valueSerde);
62 |
63 | /**
64 | * Set new serde for this output. Serdes are configured using properties of the test topology.
65 | *
66 | * @param keySerde The serializer/deserializer to be used for the keys in the output
67 | * @param valueSerde The serializer/deserializer to be used for the values in the output
68 | * @return Copy of current {@code TestOutput} with provided serdes
69 | */
70 | TestOutput configureWithSerde(Serde keySerde, Serde valueSerde);
71 |
72 | /**
73 | * Set new key serde for this output.
74 | *
75 | * @param keySerde The serializer/deserializer to be used for the keys in the output
76 | * @return Copy of current {@code TestOutput} with provided key serde
77 | */
78 | TestOutput withKeySerde(Serde keySerde);
79 |
80 | /**
81 | * Set new key serde for this output. Serde is configured using properties of the test topology.
82 | *
83 | * @param keySerde The serializer/deserializer to be used for the keys in the output
84 | * @return Copy of current {@code TestOutput} with provided key serde
85 | */
86 | TestOutput configureWithKeySerde(Preconfigured extends Serde> keySerde);
87 |
88 | /**
89 | * Set new key serde for this output. Serde is configured using properties of the test topology.
90 | *
91 | * @param keySerde The serializer/deserializer to be used for the keys in the output
92 | * @return Copy of current {@code TestOutput} with provided key serde
93 | */
94 | TestOutput configureWithKeySerde(Serde keySerde);
95 |
96 | /**
97 | * Set new value serde for this output.
98 | *
99 | * @param valueSerde The serializer/deserializer to be used for the values in the output
100 | * @return Copy of current {@code TestOutput} with provided value serde
101 | */
102 | TestOutput withValueSerde(Serde valueSerde);
103 |
104 | /**
105 | * Set new value serde for this output. Serde is configured using properties of the test topology.
106 | *
107 | * @param valueSerde The serializer/deserializer to be used for the values in the output
108 | * @return Copy of current {@code TestOutput} with provided value serde
109 | */
110 | TestOutput configureWithValueSerde(Preconfigured extends Serde> valueSerde);
111 |
112 | /**
113 | * Set new value serde for this output. Serde is configured using properties of the test topology.
114 | *
115 | * @param valueSerde The serializer/deserializer to be used for the values in the output
116 | * @return Copy of current {@code TestOutput} with provided value serde
117 | */
118 | TestOutput configureWithValueSerde(Serde valueSerde);
119 |
120 | /**
121 | * Type-casts the key and value to the given types.
122 | *
123 | * A type-cast is useful if you have general-purpose serde, such as Json or Avro, which is used for different types
124 | * in input and output. Thus, instead of unnecessarily overriding the serde, this method just casts the output.
125 | *
126 | * @param keyType the new key type.
127 | * @param valueType the new value type.
128 | * @return Copy of current {@code TestOutput} with provided types
129 | */
130 | default TestOutput withTypes(final Class keyType, final Class valueType) {
131 | return (TestOutput) this;
132 | }
133 |
134 | /**
135 | * Type-casts the key to the given type.
136 | *
137 | * A type-cast is useful if you have general-purpose serde, such as Json or Avro, which is used for different types
138 | * in input and output. Thus, instead of unnecessarily overriding the serde, this method just casts the output.
139 | *
140 | * @param keyType the new key type.
141 | * @return Copy of current {@code TestOutput} with provided key type
142 | */
143 | default TestOutput withKeyType(final Class keyType) {
144 | return (TestOutput) this;
145 | }
146 |
147 | /**
148 | * Type-casts the value to the given type.
149 | *
150 | * A type-cast is useful if you have general-purpose serde, such as Json or Avro, which is used for different types
151 | * in input and output. Thus, instead of unnecessarily overriding the serde, this method just casts the output.
152 | *
153 | * @param valueType the new value type.
154 | * @return Copy of current {@code TestOutput} with provided value type
155 | */
156 | default TestOutput withValueType(final Class valueType) {
157 | return (TestOutput) this;
158 | }
159 |
160 | /**
161 | * Reads the next value from the output stream.
162 | * Usually, you should not need to call this. The recommended way should be to use either
163 | *
164 | * - the {@link #expectNextRecord()} and {@link #expectNoMoreRecord()} methods OR
165 | * - the iterable interface (via {@link #iterator()}.
166 | *
167 | *
168 | * @return The next value in the output stream depending on the output type (stream or table semantics). {@code
169 | * null} if no more values are present.
170 | */
171 | ProducerRecord readOneRecord();
172 |
173 | /**
174 | * Reads the next record and creates an {@link Expectation} for it.
175 | *
176 | * @return An {@link Expectation} containing the next record from the output.
177 | */
178 | Expectation expectNextRecord();
179 |
180 | /**
181 | * Reads the next record from the output and expects it to be the end of output.
182 | *
183 | * @return An {@link Expectation} containing the next record from the output.
184 | */
185 | Expectation expectNoMoreRecord();
186 |
187 | /**
188 | * Interpret the output with {@link org.apache.kafka.streams.kstream.KTable} semantics (each key only once).
189 | * Note: once the first value of the stream has been read or the iterator has be called, you cannot switch
190 | * between the output types any more.
191 | * @return Current output with {@link org.apache.kafka.streams.kstream.KTable} semantics
192 | */
193 | TestOutput asTable();
194 |
195 | /**
196 | * Interpret the output with {@link org.apache.kafka.streams.kstream.KStream} semantics (each key multiple
197 | * times).
198 | * This is the default, there should usually be no need to call this method.
199 | * Note: once the first value of the stream has been read or the iterator has be called, you cannot switch
200 | * between the output types any more.
201 | *
202 | * @return Current output with {@link org.apache.kafka.streams.kstream.KStream} semantics
203 | */
204 | TestOutput asStream();
205 |
206 | /**
207 | * Convert the output to a {@link java.util.List}.
208 | *
209 | * @return A {@link java.util.List} representing the output
210 | */
211 | List> toList();
212 | }
213 |
214 |
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests/src/test/avro/City.avsc:
--------------------------------------------------------------------------------
1 | {
2 | "type": "record",
3 | "name": "City",
4 | "namespace": "com.bakdata.fluent_kafka_streams_tests.test_types",
5 | "fields": [
6 | {
7 | "name": "name",
8 | "type": "string"
9 | },
10 | {
11 | "name": "inhabitants",
12 | "type": "int"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests/src/test/avro/Person.avsc:
--------------------------------------------------------------------------------
1 | {
2 | "type": "record",
3 | "name": "Person",
4 | "namespace": "com.bakdata.fluent_kafka_streams_tests.test_types",
5 | "fields": [
6 | {
7 | "name": "name",
8 | "type": "string"
9 | },
10 | {
11 | "name": "city",
12 | "type": "string"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests/src/test/java/com/bakdata/fluent_kafka_streams_tests/CountInhabitantsWithAvroTest.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;
26 |
27 | import com.bakdata.fluent_kafka_streams_tests.test_applications.CountInhabitantsWithAvro;
28 | import com.bakdata.fluent_kafka_streams_tests.test_types.City;
29 | import com.bakdata.fluent_kafka_streams_tests.test_types.Person;
30 | import org.apache.kafka.common.serialization.Serdes;
31 | import org.junit.jupiter.api.AfterEach;
32 | import org.junit.jupiter.api.BeforeEach;
33 | import org.junit.jupiter.api.Test;
34 |
35 |
36 | class CountInhabitantsWithAvroTest {
37 |
38 | private final TestTopology testTopology =
39 | new TestTopology<>(CountInhabitantsWithAvro::getTopology, CountInhabitantsWithAvro.getKafkaProperties());
40 |
41 | @BeforeEach
42 | void start() {
43 | this.testTopology.start();
44 | }
45 |
46 | @AfterEach
47 | void stop() {
48 | this.testTopology.stop();
49 | }
50 |
51 | @Test
52 | void shouldAggregateInhabitants() {
53 | this.testTopology.input()
54 | .add(new Person("Huey", "City1"))
55 | .add(new Person("Dewey", "City2"))
56 | .add(new Person("Louie", "City1"));
57 |
58 | this.testTopology.tableOutput().withValueType(City.class)
59 | .expectNextRecord().hasKey("City1").hasValue(new City("City1", 2))
60 | .expectNextRecord().hasKey("City2").hasValue(new City("City2", 1))
61 | .expectNoMoreRecord();
62 | }
63 |
64 | @Test
65 | void shouldWorkForEmptyInput() {
66 | this.testTopology.tableOutput().withSerde(Serdes.String(), Serdes.Long())
67 | .expectNoMoreRecord();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/fluent-kafka-streams-tests/src/test/java/com/bakdata/fluent_kafka_streams_tests/CountInhabitantsWithProtoTest.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;
26 |
27 | import static com.bakdata.fluent_kafka_streams_tests.test_types.proto.CityOuterClass.City;
28 | import static com.bakdata.fluent_kafka_streams_tests.test_types.proto.PersonOuterClass.Person;
29 |
30 | import com.bakdata.fluent_kafka_streams_tests.test_applications.CountInhabitantsWithProto;
31 | import org.apache.kafka.common.serialization.Serdes;
32 | import org.junit.jupiter.api.AfterEach;
33 | import org.junit.jupiter.api.BeforeEach;
34 | import org.junit.jupiter.api.Test;
35 |
36 | class CountInhabitantsWithProtoTest {
37 |
38 | private final TestTopology