2010-10-08 109 views
2

我有一種方法,試圖調用內存中的圖像轉換器,如果失敗,然後嘗試在磁盤上執行圖像轉換。 (在內存中的圖像轉換器將嘗試分配圖像的第二個副本,因此,如果原來是非常大的,我們可能沒有足夠的內存吧。)JUnit可以模擬OutOfMemoryErrors嗎?

public BufferedImage convert(BufferedImage img, int type) { 
    try { 
    return memory_converter.convert(type); 
    } 
    catch (OutOfMemoryError e) { 
    // This is ok, we just don't have enough free heap for the conversion. 
    } 

    // Try converting on disk instead. 
    return file_converter.convert(img, type); 
} 

我想編寫單元測試運行每個代碼路徑的JUnit,但是運行JUnit時不夠方便,因此強制執行OutOfMemoryError。有沒有辦法在JUnit中模擬OutOfMemoryError

我想到我可以製作一個假的子類BufferedImage,它會在第一次調用內存轉換器調用的方法時拋出OutOfMemoryError,但隨後在後續調用中表現正常。不過,這看起來像是黑客。

回答

6

你應該嘲笑出你的轉換器,而不是使用一個真正的。

一旦你這樣做了,當你調用convert()方法時,你只需讓你的模擬庫拋出一個新的OOME。

例如,JMock的你可以這樣做:

allowing(mockConverter).convert(with(any(int.class))); 
will(throwException(new OutOfMemoryError())); 
3

注入存根或模擬memory_converterconvert()方法拋出OutOfMemryError

它發生,我認爲我可以做BufferedImage的假子類,拋出一個OutOfMemoryError在第一時間被稱爲通過在內存中的轉換器調用的方法,但隨後表現正常,在後續調用。不過,這看起來像是黑客。

模擬框架通常非常強大,應該讓你指定這種行爲。例如,JMock的:

http://www.jmock.org/returning.html

連續通話

有兩種方法在不同的調用返回不同的值返回不同的值。第一種方法是定義多個預期和返回來自每一個不同的值:

oneOf (anObject).doSomething(); will(returnValue(10)); 
oneOf (anObject).doSomething(); will(returnValue(20)); 
oneOf (anObject).doSomething(); will(returnValue(30)); 

doSomething的的第一次調用將返回圖10,第二20和第三30

2

它發生,我認爲我可以 做出的BufferedImage 拋出一個OutOfMemoryError的 第一次通過調用方法的假子 內存轉換器被調用,但 然後在後續的 調用中正常運行。不過,這看起來像是黑客。

你在這裏正確的道路上。嘲笑物體正是這些類型的東西有益的。你並不在意OutOfMemory錯誤是否合法,你只是想確保它被拋出/被捕獲並且另一個路徑被執行。把它嘲笑出來,你會很開心。

-2

OutOfMemoryError異常的處理和它的測試是非常困難的。你不能用模擬來測試它。根據哪個地方的OutOfMemoryError異常發生的影響可能會非常不同。問題是,該OutOfMemoryError異常無法通過你的調用代碼。

如果你想要一個真正的測試,那麼你需要在第二個線程內存中分配,併產生一個OutOfMemoryError。這應該重複多次以查看不同的效果。

如果你只想測試你的catch塊,那麼你可以嘲笑它。

因爲OutOfMemoryError可能會在應用程序中的任何其他線程上產生致命錯誤,所以應該阻止它。我認爲更好的解決方法是計算的可用內存。所需的內存大小,並在發生異常之前調用磁盤轉換。

+0

我看到檢查空閒堆的數量的問題是,發現它太少不能保證分配將失敗---嘗試分配可能會導致垃圾回收器釋放足夠的堆以使其成功。 – uckelman 2010-10-09 17:16:51