2012-02-03 62 views
3

我需要測試類SportCar,它擴展了汽車的代碼。問題是,當我創建我的對象在測試JMockit:如何避免超的構造

SportCar car = new SportCar(); 

它還將從父類,例如Car()調用構造函數。這些構造函數做了很多事情,有很多環境依賴關係,並且需要很多我沒有的配置文件,所以我想創建一個SportCar實例而不調用繼承的構造函數。

我知道這個問題的唯一解決方案是創建一個樣機的汽車中,我改寫的構造函數($ INIT)和靜態塊($ clinit)。但現在我的問題是,如果我的層次結構中存在許多類(SportCar擴展Car,擴展了擴展B的C繼承擴展C ...),我想避免所有構造函數,會發生什麼?我應該爲所有以前的課程創建Mocks嗎?

class A extends B{ 
    public A(){ 
     // Plenty of things to avoid during tests 
    } 
} 

class Car extends A{ 
    public Car(){ 
     // Plenty of things to avoid during tests 
    } 
} 

class SportCar extends Car(){ 
} 
+3

如果你想有一個類跑車不具備汽車類的所有行李,然後沒有從車,就這麼簡單繼承。我覺得Car應該不是一個班級,而是一個界面。 – 2012-02-03 13:22:20

+2

同意@Hovercraft在這種情況下,繼承是邪惡的。改用組合,並實現接口。如果你想「共享邏輯」爲所有的汽車,把它在你注入SportCar(和取其他車需要它)的合作者對象 - 你可以有一個合作者對象的多種實現,這將實現相同的功能,你具有繼承性,但以更簡潔的方式 - 使測試更容易,這通常是良好設計的良好指標。 – Guillaume 2012-02-03 13:30:20

+0

這是舊代碼,我不能改變,但無論如何,我不是說SportCar不需要Car的構造函數的繼承代碼。我只是表示我不想在測試期間調用此代碼。我的意思是,SportCar需要繼承Car的構造函數中的代碼,但因爲我想要一個單獨的(單元)測試,所以我不想在測試過程中調用很多類。無論如何,我知道設計很糟糕:在構造函數中有這樣的事情。有這麼多的依賴關係... – 2012-02-03 13:41:46

回答

1

Car創建一個受保護的「什麼都不做」的構造,並在SportsCar受保護的構造函數調用了它,並調用從您的測試類,可以看到構造順便說一句 - 它擁有的權限做所以。

這可以被認爲是「可測試性設計」圖案的輕微拉伸。

+1

僅僅爲了測試而在您的類中創建特殊的構造函數顯然是錯誤的。更好的方法是從Car構造函數調用某個方法,爲SportsCar類創建一個子類並覆蓋包含所有加載步驟的方法。 – 2012-02-03 13:27:39

+0

謝謝你們兩位。是的,我知道有更好的方法可以通過重構我們的代碼來避免這種可怕的情況,但是這是一個龐大的項目,它帶有舊代碼,沒有單元測試,所以我期望創建單元測試,但不要改變測試中的代碼:(我的問題更多的是關於JMockit ...在設計方面,我還希望有一個不同的場景。 – 2012-02-03 13:35:27

1

可以抑制使用PowerMock

suppress(constructor(EvilParent.class)); 

然而父類的構造,如果你做了很多的單元測試,它可能是值得搞清楚如何捏造出來的enironment爲好。或者說服其他開發者讓你做一些重構,至少允許服務注入。

+0

+1「說服其他開發人員」。但我不相信,一個模擬框架提供 – Raedwald 2012-02-03 14:10:04

+0

我自己從來沒有使用過這個功能,但是PowerMock使用自定義類加載器來操縱字節碼本身,以允許靜態方法被嘲笑 – 2012-02-03 14:12:55

+0

我發現PowerMock字節碼操作有時會引起意想不到的複雜情況。絕對強大,但它必須是相當侵入性的。 – AHungerArtist 2012-02-03 15:36:23

4

如果您正在使用jmockit,你不必做任何事情,因爲所有的超類的構造函數默認嘲笑。在你單元測試的方法,你可以做:

public void testMockedStuff(@Mocked final ClassToBeMocked instance) { 

有嘲笑你的東西。你甚至不必自己創建實例。 然後,您可以修改註釋參數以排除您從模擬中獲取的方法。