英文:
How to test the send method from a Kafka Producer with callback using 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");
}
}
我应该如何正确模拟这种情况?
英文:
I am trying to test a method and for that I am using mockito. However, my mock is not getting inside into the if's condition and goes directly to the flush's line.
I would like to test the follow situation:
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();
}
And what I'm doing is it:
@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");
}
}
What can I do to mock this situation correctly?
答案1
得分: 2
使用以下 lambda 表达式,您正在实现 Callback 接口(接口 Callback)的 onCompletion 方法:
(metadata, exception) -> {
if(exception == null ) {
LOGGER.info("OK");
}else{
LOGGER.info("NOK");
}
}
由于您正在模拟 KafkaProducer 的 send 方法调用,该回调不会被调用。
因此,为了能够进入回调调用,您需要捕获 Callback 参数,并按如下方式调用 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);
英文:
By using the lambda expression below, you are implementing the onCompletion method of the Callback interface (Interface Callback)
(metadata, exception) -> {
if(exception == null ) {
LOGGER.info("OK");
}else{
LOGGER.info("NOK");
}
}
And since you are mocking the KafkaProducer send method call, that callback won't be called.
So, to be able to get inside the callback call, you have to capture the Callback argument and call the onCompletion method as below:
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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论