2016-10-04 89 views
2

我正在使用Java和Mockito來模擬一些單元測試的方法。我想在下面的代碼中嘲笑生產者,這樣我就可以測試拋出異常時發送的日誌消息。我試圖嘲笑未來,但是我得到了future.get()方法不能被嘲笑的錯誤,並且類是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); 
    } 
} 

回答

3

卡夫卡提供MockProducer類,您可以將其注入課堂進行測試。您可以將類中的producer設置爲JUnit @Before -annotated設置方法中的MockProducer實例。從MockProducer的參考文檔:

生產者接口的一個模擬,您可以使用它來測試使用Kafka的代碼。

默認情況下,該模擬將同步完成每個發送呼叫成功。然而,它可以配置爲允許用戶控制呼叫的完成併爲生產者提供可選錯誤。

您可以使用#errorNext方法提供您想要拋入測試場景的異常。

+0

謝謝你,那很好。儘管我確實發現errorNext不能拋出發送方法可能拋出的兩種類型的異常(InterruptedException)之一。 – annedroiid

+0

它允許您指定RuntimeException類型的異常,這是InterruptedException的擴展 –

1

在沒有看到測試代碼的情況下,很難精確到這裏。兩個問題

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