模拟一个返回未来以抛出异常的方法

时间:2016-10-04 04:56:38

标签: java mockito

我使用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);
  }
}

2 个答案:

答案 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);
    }
}