英文:
Mockito Unit Tests stubbing a method throws NullPointerException
问题
我正在为下面的类中的 run()
方法编写一些单元测试:
public class TopicProcessor implements Runnable {
private final KafkaConfig config;
private final String inTopic;
private final String outTopic;
private final String inBroker;
private final String outBroker;
private KafkaConsumer<Long, byte[]> kafkaConsumer;
private KafkaProducer<Long, byte[]> kafkaProducer;
public void setKafkaConsumer(KafkaConsumer<Long, byte[]> kafkaConsumer) {
this.kafkaConsumer = kafkaConsumer;
}
public void setKafkaProducer(KafkaProducer<Long, byte[]> kafkaProducer) {
this.kafkaProducer = kafkaProducer;
}
public TopicProcessor(String topicKey, KafkaConfig config) {
this.config = config;
Map<String, Map<String, String>> mapping = this.config.getMapping(topicKey);
this.inTopic = mapping.get("in").get("topic");
this.outTopic = mapping.get("out").get("topic");
this.inBroker = mapping.get("in").get("broker");
this.outBroker = mapping.get("out").get("broker");
}
@Override
public void run() {
long now;
getKafkaConsumer().subscribe(Collections.singletonList(this.inTopic));
while (true) {
ConsumerRecords<Long, byte[]> records = getKafkaConsumer().poll(Duration.ofMillis(100));
meterInfo("consumer.received." + this.inTopic, records.count());
for (ConsumerRecord<Long, byte[]> record : records) {
now = currentTimeMillis();
histogram("consumer.latency." + this.inTopic, now - record.timestamp());
getKafkaProducer().send(new ProducerRecord<>(this.outTopic, record.key(), record.value()));
meterInfo("publisher.sent." + this.outTopic);
}
}
}
}
基本上,在 run()
方法中,我订阅了一个主题,使用 KafkaConsumer.poll()
方法轮询了所有记录,对于每条记录,我都使用了 KafkaProducer.send()
方法发送了记录。
我必须为以下情景编写单元测试:
- 测试
KafkaConsumer.poll()
方法是否调用了一次。 - 测试
KafkaProducer.send()
方法是否调用了一次。
以下是我的测试方法:
@Test
public void test(){
// 模拟
KafkaConsumer<Long, byte[]> consumerMock = mock(KafkaConsumer.class);
KafkaProducer<Long, byte[]> producerMock = mock(KafkaProducer.class);
// 测试数据
Map<TopicPartition, List<ConsumerRecord<Long, byte[]>>> records = new LinkedHashMap<>();
records.put(new TopicPartition("topic", 0), new ArrayList<>());
ConsumerRecords<Long, byte[]> consumerRecords = new ConsumerRecords<>(records);
ProducerRecord<Long, byte[]> producer_record = new ProducerRecord<>("topic", 1, 0L, 1L, new byte[]{'a'});
// 创建对象以调用方法
KafkaConfig kafkaConfig = new KafkaConfig(yamlConfig);
TopicProcessor topicProcessor = new TopicProcessor("pacing_record", kafkaConfig);
// 桩方法 - poll 和 send
when(consumerMock.poll(Duration.ofMillis(anyInt()))).thenReturn(consumerRecords);
doReturn("sent").when(producerMock.send(producer_record, null));
// 通过 setter 方法注入模拟对象
topicProcessor.setKafkaConsumer(consumerMock);
topicProcessor.setKafkaProducer(producerMock);
// 调用上述类中的 run() 方法以验证是否调用了 kafka 方法
topicProcessor.run();
verify(consumerMock, times(1)).poll(Duration.ofMillis(anyInt()));
}
在上述测试方法中的以下行会抛出 NullPointerException:
when(kafkaConsumerMock.poll(Duration.ofMillis(anyInt()))).thenReturn(consumerRecords);
有人知道如何正确地对方法进行桩方法,并验证是否被调用了吗?
英文:
I am writing some unit tests for the run()
method in the below class
public class TopicProcessor implements Runnable {
private final KafkaConfig config;
private final String inTopic;
private final String outTopic;
private final String inBroker;
private final String outBroker;
private KafkaConsumer<Long, byte[]> kafkaConsumer;
private KafkaProducer<Long, byte[]> kafkaProducer;
public void setKafkaConsumer(KafkaConsumer<Long, byte[]> kafkaConsumer) {
this.kafkaConsumer = kafkaConsumer;
}
public void setKafkaProducer(KafkaProducer<Long, byte[]> kafkaProducer) {
this.kafkaProducer = kafkaProducer;
}
public TopicProcessor(String topicKey, KafkaConfig config) {
this.config = config;
Map<String, Map<String, String>> mapping = this.config.getMapping(topicKey);
this.inTopic = mapping.get("in").get("topic");
this.outTopic = mapping.get("out").get("topic");
this.inBroker = mapping.get("in").get("broker");
this.outBroker = mapping.get("out").get("broker");
}
@Override
public void run() {
long now;
getKafkaConsumer().subscribe(Collections.singletonList(this.inTopic));
while (true) {
ConsumerRecords<Long, byte[]> records = getKafkaConsumer().poll(Duration.ofMillis(100));
meterInfo("consumer.received." + this.inTopic, records.count());
for (ConsumerRecord<Long, byte[]> record : records) {
now = currentTimeMillis();
histogram("consumer.latency." + this.inTopic, now - record.timestamp());
getKafkaProducer().send(new ProducerRecord<>(this.outTopic, record.key(), record.value()));
meterInfo("publisher.sent." + this.outTopic);
}
}
}
Basically, In the run()
method, I am subscribed to a topic, polled all records using KafkaConsumer.poll()
method and for each record, I am sending the record using KafkaProducer.send()
method.
I have to write unit tests for below scenario : -
- Test that
KafkaConsumer.poll()
method called one time - Test that
KafkaProducer.send()
method called one time
Below is my Test method: -
@Test
public void test(){
//Mocks
KafkaConsumer<Long, byte[]> consumerMock = mock(KafkaConsumer.class);
KafkaProducer<Long, byte[]> producerMock = mock(KafkaProducer.class);
//test data
Map<TopicPartition, List<ConsumerRecord<Long, byte[]>>> records = new LinkedHashMap<>();
records.put(new TopicPartition("topic", 0), new ArrayList<>());
ConsumerRecords<Long, byte[]> consumerRecords = new ConsumerRecords<>(records);
ProducerRecord<Long, byte[]> producer_record = new ProducerRecord<Long, byte[]>("topic", 1, 0L, 1L, new byte[]{'a'});
//object creation to call the method
KafkaConfig kafkaConfig = new KafkaConfig(yamlConfig);
TopicProcessor topicProcessor = new TopicProcessor("pacing_record", kafkaConfig);
//stubbing Kafka methods - poll and send
when(consumerMock.poll(Duration.ofMillis(anyInt()))).thenReturn(consumerRecords);
doReturn("sent").when(producerMock.send(producer_record, null));
//Injecting mocks thorugh setter method
topicProcessor.setKafkaConsumer(consumerMock);
topicProcessor.setKafkaProducer(producerMock);
//calling a class method run() from above class to verify that kafka methods are called
topicProcessor.run();
verify(consumerMock, times(1)).poll(Duration.ofMillis(anyInt()));
}
Below line in the above test method throws NullPointerException
when(kafkaConsumerMock.poll(Duration.ofMillis(anyInt()))).thenReturn(consumerRecords);
Anyone know how to correctly stub the method and verify it is called or not?
答案1
得分: 0
when(kafkaConsumerMock.poll(Duration.ofMillis(anyInt())))
这是对Mockito的错误使用。`any*` 方法只应作为模拟方法的直接参数使用。
我认为你在这里想表达的是:“对于任何持续时间,我不关心它有多长”。如果是这样,你可以表示为:
when(kafkaConsumerMock.poll(any(Duration.class)))
或者
when(kafkaConsumerMock.poll(any()))
如果没有歧义性重载。
类似地,用于验证:
verify(kafkaConsumerMock, times(1)).poll(any(Duration.class))
英文:
when(kafkaConsumerMock.poll(Duration.ofMillis(anyInt())))
This is an incorrect usage of Mockito. The any*
methods should only be used as the direct parameters to the mocked method.
I think what you're trying to say here is "for any duration, I don't care how long it is". If so, you can express that as:
when(kafkaConsumerMock.poll(any(Duration.class))
or
when(kafkaConsumerMock.poll(any())
if there is no ambiguous overload.
Similarly, to verify:
verify(kafkaConsumerMock, times(1)).poll(any(Duration.class))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论