I'm using spring cloud stream to modify a Kafka Topic and write the resulting data with ".toTable()" to a table. In the application.yaml I will set the input and output bindings. This works fine on the Kafka cluster but not with my current test setup.
@Configuration
public class ObjectTopology {
@Bean
public static Serde<Object> objSerde() {
return new ProtobufSerde<>(Object.parser());
}
@Bean
public Function<KStream<String, Object>, KTable<String, Object>> obj() {
return objKStream -> objKStream
.transform((TransformerSupplier<String, Object, KeyValue<String, Object>>) SomeTransformer::new)
.toTable();
}
}
application.yaml:
spring.cloud.stream.bindings:
obj-in-0:
destination: input-name
obj-out-0:
destination: output-name
How would I access the KTable generated by "toTable" in the code below? Is there a way to use the spring-cloud-stream bindings in my unit tests?
ObjectTopology objectTopology = new ObjectTopology();
StreamsBuilder streamsBuilder = new StreamsBuilder();
Serde<String> keySerde = Serdes.String();
Serde<Object> valueSerde = objSerde();
KStream<String, Object> objKStream = streamsBuilder.stream("input-topic-name", Consumed.with(keySerde, valueSerde));
objectTopology.obj().apply(objKStream);
TopologyTestDriver topologyTestDriver = new TopologyTestDriver(streamsBuilder.build());
TestInputTopic<String, Object> objTestInputTopic = topologyTestDriver.createInputTopic("input-topic-name", keySerde.serializer(), valueSerde.serializer());
KeyValueStore<String, Object> objStore = topologyTestDriver.getKeyValueStore("???"); // I would like to use the name defined by the output binding in application.yaml "output-name"
Object object = createObject();
objTestInputTopic.pipeInput("elem_0", object);
Object result = objStore.get("elem_0");
assertThat(result).isEqualTo(object);
To access the KTable
generated by the toTable
method in your unit test, you can use the TopologyTestDriver
's getKeyValueStore
method to retrieve the store associated with the output binding.
In your code, you can use the getKeyValueStore
method like this:
TopologyTestDriver topologyTestDriver = new TopologyTestDriver(streamsBuilder.build());
KeyValueStore<String, Object> objStore = topologyTestDriver.getKeyValueStore("output-name");
This will retrieve the store associated with the output binding defined in your application.yaml
file, which you can then use to access the values in the KTable
.
Alternatively, you can use the @Output
annotation to inject the output binding's MessageChannel
into your test, and then use the send
method to send messages to the output binding. You can then use the TopologyTestDriver
's createInputTopic
method to create a test input topic that represents the output binding, and use this input topic to verify that the messages were sent tothe output binding as expected.
Here's an example of how you might use the @Output
annotation in your test:
@Autowired
@Output("obj-out-0")
private MessageChannel outputChannel;
@Test
public void testOutputBinding() {
// create a message to send to the output binding
Message<Object> message = MessageBuilder.withPayload(createObject()).build();
// send the message to the output binding
outputChannel.send(message);
// create a test input topic representing the output binding
TestInputTopic<String, Object> objTestInputTopic = topologyTestDriver.createInputTopic("obj-out-0", keySerde.serializer(), valueSerde.serializer());
// verify that the message was sent to the output binding
assertThat(objTestInputTopic.readKeyValue()).isEqualTo(new KeyValue<>("elem_0", createObject()));
}
toTable
creates an internal topic. You should probably use topologyTestDriver.createOutputTopic to read it.
For the naming, there is https://kafka.apache.org/26/javadoc/org/apache/kafka/streams/kstream/KStream.html#toTable--
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.