0

I am trying to mock my response from KafkaTemplate.send() My main class is setup like this

  @Override
  public QueryServiceSendStatus sendMessage(
      String topic, Integer partition, String key, byte[] value, List<Header> recordHeaders) {

    try {
      ListenableFuture result =
          kafkaTemplate
              .send(new ProducerRecord<>(topic, partition, key, value, recordHeaders));

Notice I don't have callbacks on my Listenable Future and have the class marked @Async, I have tried implementing this with callbacks as well and still run into the same issue. When running my full application and running a sort of smoke test the kafka code works as expected and writes the correct data onto its intended topic.

Here is my test:

@SpringBootTest
@ExtendWith(MockitoExtension.class)
class QueryServiceProducerTest {
  @InjectMocks private QueryServiceProducer classUnderTest;
  @Mock KafkaTemplate<String, byte[]> template;
  QueryServiceRequest queryServiceRequest;
  QueryServiceSendStatus expectedStatus;

  @BeforeEach
  void setup() throws ExecutionException, InterruptedException {
    int offset = 0;
    expectedStatus =
        QueryServiceSendStatus.builder()
            .offset(0L)
            .partition(0)
            .error(null)
            .partition(0)
            .topic("topic")
            .timestamp(123L)
            .build();
    queryServiceRequest =
        new QueryServiceRequest(String.valueOf(UUID.randomUUID()), "data", "topic");

    RecordMetadata recordMetadata =
            new RecordMetadata(
                    new TopicPartition(queryServiceRequest.getTopic(), offset), 0L, 0L, 123L, 0L, 0, 0);

    SettableListenableFuture<SendResult<String, byte[]>> future = new SettableListenableFuture<>();
    future.set(new SendResult<>(new ProducerRecord<>("topic", 0, queryServiceRequest.getId(), "data".getBytes(), null), recordMetadata));

    given(template.send(any(ProducerRecord.class)))
        .willReturn(future); // Have Also used when().thenReturn
  }

  @Test
  void testQueryServiceProducerIsOK() {
    QueryServiceSendStatus status =
        classUnderTest.sendMessage(
            queryServiceRequest.getTopic(),
            0,
            queryServiceRequest.getId(),
            queryServiceRequest.getData().getBytes(),
            null);
    Assertions.assertEquals(expectedStatus, status);
  }

In my main class I want to do some stuff on the future to get the RecordMetadata to build my response to the class that called the producer (You can see I have am returning an object called QueryServiceSendStatus that I will be storing in a DB). The problem is during my test when I call kafkaTemplate.send(new ProducerRecord<>()); result variable never gets populated even though I am mocking the kafkaTemplate.

I have tried mocking the SettableListenerFuture along with the SendResult that I use to create the SettableListenerFuture, but for some reason when send() is always called it is null.

Beez
  • 478
  • 9
  • 23
  • Perhaps you imported the wrong `any()` method statically, are you using Hamcrest also? – andy Jul 27 '22 at 18:30
  • I was using Mockito.any() @andy – Beez Jul 27 '22 at 18:45
  • Try mocking the interface instead - see https://stackoverflow.com/questions/57475464/how-to-mock-result-from-kafkatemplate/57478836#57478836 – Gary Russell Jul 27 '22 at 20:39
  • @GaryRussell -- Sender no longer has the NoArgsConstructor making it hard to instantiate Sender, also since I am not using callbacks is that the best way to approach this? – Beez Jul 28 '22 at 15:30
  • It is not clear what you mean, I have no idea what `Sender` is; edit the question with much more detail. – Gary Russell Jul 28 '22 at 15:40
  • @GaryRussell -- Referring to your link you gave me in above comment. – Beez Jul 28 '22 at 17:00
  • Post an [MCRE](https://stackoverflow.com/help/minimal-reproducible-example) someplace so I can see what you are doing wrong. – Gary Russell Jul 28 '22 at 17:08

0 Answers0