我使用Java和Mockito来模拟一些单元测试方法。我想在下面的代码中模拟生成器,以便我可以测试抛出异常时发送的日志消息。我试着模拟未来然而我得到的错误是future.get()方法不能被模拟,RecordMetadata
类是final并且不能被模拟。任何帮助将不胜感激。
以下示例中的制作人是KafkaProducer
。
public void send(Log log){
Future<RecordMetadata> future = producer.send(new ProducerRecord<(this.topic, record));
try {
RecordMetadata recordMetadata = send.get();
} catch (InterruptedException e) {
LOG.error("Sending the message to kafka was interrupted. "+e);
}
}
答案 0 :(得分:4)
Kafka提供了一个MockProducer
课程,您可以将其注入课堂进行测试。您可以在JUnit producer
- 带注释的设置方法中将类中的MockProducer
设置为@Before
的实例。来自MockProducer
的参考文档:
可用于测试使用Kafka的代码的生产者界面的模拟。
默认情况下,此模拟将同步成功完成每个发送调用。但是,它可以配置为允许用户控制调用的完成,并为生产者提供可选的错误。
您可以使用#errorNext
方法提供要在测试场景中抛出的异常。
答案 1 :(得分:2)
如果没有看到您的测试代码,这里很难准确。两个问题
1)RecordMetadata不能用于Mockito模拟,这是Mockito的已知限制。相反,您可以使用其公共构造函数创建RecordMetadata的虚拟实例。
2)KafkaProducer可以被Mockito嘲笑,但你需要一个两阶段的方法。首先,模拟KafkaProducer返回一个Future,其次Future也是一个返回一些已知值的模拟。
public class ServiceTest {
@Mock
private KafkaProducer<String, Integer> producer;
@Mock
private Future<RecordMetadata> future;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void success() throws Exception {
RecordMetadata dummyRecord = new RecordMetadata(null, 0L, 0L, 0L, 0L, 0, 0);
when(producer.send(any())).thenReturn(future);
when(future.get()).thenReturn(dummyRecord);
producer.send(null);
}
@Test
public void timeout() throws Exception {
when(producer.send(any())).thenReturn(future);
when(future.get()).thenThrow(new TimeoutException("timeout"));
producer.send(null);
}
}