Java 模拟返回未来以引发异常的方法

Java 模拟返回未来以引发异常的方法,java,mockito,Java,Mockito,我正在使用Java和Mockito来模拟一些用于单元测试的方法。我想在下面的代码中模拟生产者,以便在抛出异常时测试发送的日志消息。我尝试模拟future,但是我得到一个错误,即future.get()方法不能模拟,并且RecordMetadata类是最终类,不能模拟。任何帮助都将不胜感激 下面示例中的制作人是一个KafkaProducer public void send(Log log){ Future<RecordMetadata> future = producer.sen

我正在使用Java和Mockito来模拟一些用于单元测试的方法。我想在下面的代码中模拟生产者,以便在抛出异常时测试发送的日志消息。我尝试模拟future,但是我得到一个错误,即future.get()方法不能模拟,并且
RecordMetadata
类是最终类,不能模拟。任何帮助都将不胜感激

下面示例中的制作人是一个
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);
  }
}
公共作废发送(日志){
Future Future=producer.send(new ProducerRecordKafka提供了一个类,您可以将该类中的
producer
设置为JUnit
@Before
-注释设置方法中的
MockProducer
的实例。从
MockProducer
的参考文档中:

可用于测试使用Kafka的代码的生产者界面的模拟。

默认情况下,此模拟将成功同步完成每个发送调用。但是,可以将其配置为允许用户控制调用的完成,并提供可选错误供生产者抛出


您可以使用该方法提供要在测试场景中抛出的异常。

如果不查看您的测试代码,则很难在此处精确说明。有两个问题

1) RecordMetadata不能用于Mockito mock,这是Mockito的已知限制。相反,您可以使用其公共构造函数创建RecordMetadata的虚拟实例

2) KafkaProducer可以被Mockito模仿,但是你需要一个两阶段的方法。首先,模仿KafkaProducer返回一个未来,其次,这个未来也是一个返回一些已知值的模仿

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);
    }
}
公共类服务测试{
@嘲弄
私人卡夫卡制作人;
@嘲弄
私人未来;
@以前
公共作废设置(){
initMocks(this);
}
@试验
public void success()引发异常{
RecordMetadata dummyRecord=新的RecordMetadata(null,0L,0L,0L,0L,0,0);
when(producer.send(any())。然后return(future);
when(future.get()).thenReturn(dummyRecord);
producer.send(空);
}
@试验
public void timeout()引发异常{
when(producer.send(any())。然后return(future);
when(future.get()).thenthow(newtimeoutexception(“timeout”));
producer.send(空);
}
}

谢谢,效果很好。尽管我觉得errorNext不能抛出两种类型的异常之一(InterruptedException)有点傻它允许您指定RuntimeException类型的异常,这就是InterruptedExceptionextends@GaryO'Donoghue InterruptedException扩展异常而非RuntimeException