Как протестировать метод отправки от производителя Kafka с обратным вызовом с использованием mockito?

#java #apache-kafka #mockito

#java #apache-kafka #mockito

Вопрос:

Я пытаюсь протестировать метод, и для этого я использую mockito. Однако мой макет не попадает внутрь условия if и переходит непосредственно к строке flush.

Я хотел бы протестировать следующую ситуацию:

 public class SomeClass{
     @Autowired
     private Producer<String, SpecificRecord> producer;

     private static final Logger LOGGER = Logger.Factory.getLogger(SomeClass.class);

     public void sendMessage(String topic, SpecificRecord message, Map<String,String> headers){
         ProducerRecord<String, SpecificRecord> avroMessage = new ProducerRecord<>(topic, null, null, "key",message, headers);
         producer.send(avroMessage, (metadata, exception) -> {
             if(exception == null ) {
                 LOGGER.info("OK");
             }else{ 
                 LOGGER.info("NOK");
             }
         });
         producer.flush();
    }
  

И то, что я делаю, это:

 @RunWith(MockitoJUnitRunner.class)
public class SomeClassTest{
    @InjectMocks
    private SomeClass someclass;
    
    @Mock
    private Producer<String,SpecificRecord> producer;

    @Mock
    private SpecificRecord message;

    @Mock
    private Logger logger;

    @Test
    public void sendMessageTest(){
        when(producer.send(any(ProducerRecord.class),any(Callback.class))).thenReturn(null);
        doNothing().when(producer).flush();
        
        someclass.sendMessage("topic", message, new HashMap<String,String>());
        verify(logger).info("OK");
    }
}
    
  

Что я могу сделать, чтобы правильно смоделировать эту ситуацию?

Комментарии:

1. Kafka включает класс MockProducer, который вам, вероятно, следует использовать вместо этого

2. можете ли вы привести мне пример?

3. baeldung.com/kafka-mockproducer

Ответ №1:

Используя приведенное ниже лямбда-выражение, вы реализуете метод onCompletion интерфейса обратного вызова (Interface Callback)

 (metadata, exception) -> {
         if(exception == null ) {
             LOGGER.info("OK");
         }else{ 
             LOGGER.info("NOK");
         }
     }
  

И поскольку вы издеваетесь над вызовом метода отправки KafkaProducer, этот обратный вызов вызываться не будет.
Итак, чтобы иметь возможность попасть внутрь обратного вызова, вы должны захватить аргумент обратного вызова и вызвать метод onCompletion, как показано ниже:

     ArgumentCaptor<Callback> callBackCaptor = ArgumentCaptor.forClass(Callback.class);
    Mockito.verify(producer).send(any(ProducerRecord.class), callBackCaptor.capture());
    Callback kafkaCallback = callBackCaptor.getValue();
    kafkaCallback.onCompletion(new RecordMetadata(null, 0, 0, 0, 0, 0, 0), null);