2012-06-22 51 views
16

我正在使用jUnit來管理訪問數據庫的應用程序的集成測試。由於設置測試數據是一項非常耗時的操作,因此我在@BeforeClass方法中一直這樣做,該方法每個測試類只執行一次(與每個測試方法運行一次的@Before方法相反)。使用jUnit 4,我可以參數化@BeforeClass嗎?

現在我想爲數據層的配置嘗試幾個不同的排列,在每個不同的配置上運行我所有的測試。這似乎是Parameterized測試跑步者的自然使用。問題是,Parameterized將參數提供給類構造函數,並且@BeforeClass方法是抽象的,並在類構造函數之前調用。

的幾個問題,

是否Parameterized呼籲的參數每個排列的@BeforeClass方法呢,還是隻調用一次?

如果@BeforeClass方法被重複調用,有沒有辦法從裏面訪問參數值?

如果沒有這些,那麼人們會建議什麼作爲解決此問題的最佳方法?

+0

查看是否http://code.google.com/p/junitparams/可以幫助 – Jayan

+0

那麼仍然沒有辦法做到這一點? –

+1

該效果可以通過自定義測試運行器來完成。通常,您可以繼承BlockJUnit4ClassRunner。 –

回答

1

@BeforeClass在您的示例中僅被調用一次。考慮到這個名字,這在課堂上是有道理的!

如果你的測試需要不同的數據,有兩種選擇,我能想到的:

  1. 設置在@Before數據,因此它是具體的測試
  2. 集團要與運行測試將相同的數據放入單獨的測試類中,併爲每個測試類使用@BeforeClass。
+1

謝謝你澄清我對@ BeforeClass的理解。遺憾的是,你提出的兩種方法並不能解決我的大問題。方法1的問題在於我的高成本一次性初始化從一個場景變化到另一個場景,但我不想爲每個測試重複一次。方法2的問題是我必須爲每個場景編寫不同的測試類,即使我正在運行相同的測試。 –

+1

Dan,對於選項#2,您可以繼承子類。在超類中有「相同的測試」,然後每個子類都反映場景。換句話說,子類只包含@BeforeClass –

+0

這種方法在技術上是可行的,但我不覺得它有吸引力,因爲我已經有幾十個測試類,並且期望最終有數百個 –

-1

您可以在@Before方法中進行初始化,寫入實例變量但測試爲null。

@RunWith(value = Parameterized.class) 
public class BigThingTests { 
    private BigThing bigThing; 

    @Before 
    public void createBitThing() { 
    if (bigThing == null) { 
     bigThing = new BigThing(); 
    } 
    } 

... 
} 

BigThingTests一個新實例對於每組參數創建,並且bigThing設置與每個新的實例爲空。 Parameterized跑步者是單線程的,所以你不必擔心多個初始化。

+0

this.bigThing將始終爲空,因爲您爲每個@Test獲得BigThingTests的新實例。 –

0

您可以在測試類的構造函數中調用此初始化邏輯。跟蹤靜態變量中使用的最後一個參數。當它改變時,爲新參數設置類。

我想不出一個AfterClass的等價物。

+1

使用構造函數而不是'@ Before'並沒有幫助,因爲標準的JUnit 4測試運行器爲每個測試方法創建了一個新的測試類實例。所以我仍然會遇到這樣的問題:我的代價昂貴的設置代碼對於每個方法和參數的排列都會調用一次,而不是每個參數的排列只調用一次。 –

+0

好的。我已經更新了我的答案(以及我正在處理同樣問題的測試)。 – TREE

3

我想你會需要一個定製的測試跑步者。我遇到了同樣的問題(需要使用多個昂貴的配置來運行相同的測試)。您需要一種參數化設置的方法,可能使用類似於參數化運行程序使用的@Parameter註釋,但使用靜態成員字段而不使用實例字段。自定義運行器必須使用@Parameter批註找到所有靜態成員字段,然後每個靜態@Parameter字段運行一次測試類(可能使用基本的BlockJunit4ClassRunner)。 @Parameter字段應該可能是@ClassRule。

Andy on Software在開發定製測試跑步者方面做得很好,他在這些博客文章herehere中解釋得非常清楚。

+0

+1 for @ClassRule完美地工作,不會干擾參數化功能或需要定製亞軍 – bstoney

0

這是一個老問題,但我只是要解決一個可能類似的問題。我現在使用下面的解決方案,基本上是使用通用抽象基類實現TREE(更新)的答案,以避免每當需要此機制時重複。

具體測試將提供一個@Parameters方法,該方法返回一個包含供應商< T>的迭代單元素數組。然後,這些供應商將根據具體測試方法所需的實際投入量執行一次。

@RunWith(Parameterized.class) 
public class AbstractBufferedInputTest<T> { 

private static Object INPUT_BUFFER; 

private static Object PROVIDER_OF_BUFFERED_INPUT; 

private T currentInput; 

@SuppressWarnings("unchecked") 
public AbstractBufferedInputTest(Supplier<T> inputSuppler) { 
    if (PROVIDER_OF_BUFFERED_INPUT != inputSuppler) { 
     INPUT_BUFFER = inputSuppler.get(); 
     PROVIDER_OF_BUFFERED_INPUT = inputSuppler; 
    } 
    currentInput = (T) INPUT_BUFFER; 
} 

/** 
* 
* @return the input to be used by test methods 
*/ 
public T getCurrentInput() { 
    return currentInput; 
} 

} 
相關問題