2015-12-22 180 views
2

我正在爲我的代碼編寫單元測試用例。我正在使用PowerMockito和Junit。我寫了一個初始化代碼,它將處理我應用程序中所有初始化的東西。下面是我的代碼的結構方式:對多個測試類只執行一次初始化代碼

Class ServiceInitializer{ 
    public static isInitialized = Boolean.FALSE; 

    public static void initialize(){ 
     //Initilization Code Goes Here 
     isInitialized = Boolean.TRUE; 
    } 
} 

@RunWith(PowerMockRunner.class) 
class BaseTest{ 

    @Before 
    public void preTest(){ 
     //some code 
    } 


    static{ 
     if(!ServiceInitializer.isInitialized){ 
      ServiceInitializer.initialize(); 
     } 
    } 

    @After 
    public void postTest(){ 
     //some code 
    } 
} 

public TestClass1 extends BaseTest{ 
    @Test 
    public void testMethodA_1(){//test code} 

    @Test 
    public void testMethodA_2(){//test code} 

    @Test 
    public void testMethodA_3(){//test code} 
} 

public TestClass2 extends BaseTest{ 
    @Test 
    public void testMethodB_1(){//test code} 

    @Test 
    public void testMethodB_2(){//test code} 

    @Test 
    public void testMethodB_3(){//test code} 
} 

我使用JUnit和batchtest目標執行這些測試案例ant腳本下面給出:

<junit printsummary="yes" haltonfailure="yes" showoutput="yes"> 
      <classpath refid="JUnitTesting.classpath"/> 
      <batchtest haltonerror="false" haltonfailure="no" todir="${junit.output.dir}/raw"> 
       <formatter type="plain"/> 
       <formatter type="xml"/>  
       <fileset dir="${basedir}/src"> 
        <include name="**/Test*.java"/> 
       </fileset> 
      </batchtest> 
     </junit> 

我能夠只是執行測試用例很好,但它的初始化代碼寫在了BaseTest類的靜態塊中,這對我造成了問題。每當新測試類別開始執行時,「ServiceInitializer.initialize();」每次都會被調用。所以說,如果我有10個測試類,那麼這個方法會被調用10次。我想要控制它,使得它只能被執行一次,無論我有多少個測試類。我怎樣才能做到這一點?這甚至有可能與JUnit?

--Update--

我知道有可用@BeforeClass標註這正是一次爲每個測試類執行的代碼塊。但是這並不符合我的要求,因爲一旦JUnit運行其他測試類,就會調用「@BeforeClass」註釋下的方法,並且儘管在那裏進行初始化檢查後再次運行初始化代碼。

回答

3

你可以使用一個類規則:使用@ClassRule註釋

public class ServiceInitializer extends ExternalResource { 
    public static final TestRule INSTANCE = new ServiceInitializer(); 
    private final AtomicBoolean started = new AtomicBoolean(); 

    @Override protected void before() throws Throwable { 
    if (!started.compareAndSet(false, true)) { 
     return; 
    } 
    // Initialization code goes here 
    } 

    @Override protected void after() { 
    } 
} 

然後你就可以在你的測試使用:

@RunWith(PowerMockRunner.class) 
class BaseTest{ 
    @Rule 
    public PowerMockRule powerMockRule = new PowerMockRule(); 
    @ClassRule 
    public static final TestRule serviceInitializer = ServiceInitializer.INSTANCE; 

    @Before 
    public final void preTest() { 
    // some code 
    } 

    @After 
    public final void postTest() { 
    //some code 
    } 
} 

編輯:PowerMockRunner顯然不支持@ClassRule,所以我換了th e測試使用PowerMockRule。你可以從here瞭解更多關於它的信息。無論如何,我個人更喜歡自定義選手的規則。

+0

謝謝你的真棒迴應。我不確定原因,但初始化代碼沒有執行。然後我從BaseTest類中刪除了「@RunWith(PowerMockRunner.class)」註釋,然後按預期方式執行初始化代碼。你有什麼想法保持它嗎? –

+0

@Prera​​kTiwari聽起來像'PowerMockRunner'不支持類規則。我建議重構你的代碼,這樣你就不需要powermock,或者在沒有'PowerMockRunner'的情況下使用powermock – NamshubWriter

+0

接受你的答案,但PowerMock不能在沒有PowerMockRunner的情況下使用。因此,爲了完美運行,需要刪除「@RunWith(PowerMockRunner.class)」註釋,並且必須包含「@Rule public PowerMockRule powerMockRule = new PowerMockRule();」 在課堂上。您可以從[此處](https://code.google.com/p/powermock/wiki/PowerMockRule)閱讀更多內容。 –

2

您可以在JUnit中使用@BeforeClass註釋。

這將爲測試類(BaseTest)執行一次。

你甚至不需要'public static isInitialized = Boolean.FALSE;'。 只要相信JUnit。 :)

要在所有測試類之前運行,您必須創建測試套件並在測試套件類中使用@ClassRule

+0

@BeforeClass在*每個*測試類之前被調用,但是OP想要「它只被執行一次,無論我有多少個測試類」。 – meriton

+0

請參閱更新的問題。 –

0

嘗試@BeforeClass在每次測試之前僅對每個類執行一次設置。

+0

請參閱更新後的問題。 –

0

PowerMockRunner在通過標準類加載器加載測試類之後安裝自己的類加載器。 在由

@BeforeClass 

BTW註釋公共靜態方法更好地執行靜態initalizers:除非你在你測試類級別需要@PrepareForTest註釋它沒有必要運行與PowerMockRunner測試。

+0

請參閱更新的問題。 –

3

請考慮在您的ant-junit任務中使用forkmode元素。默認值是「perTest」:它爲每個測試類創建一個新的JVM。如果將forkmode定義爲「perBatch」,則只有一個JVM用於批處理。所以你的ServiceInitializer類保持初始化。

又見the help for junit task here

+0

我用''但我的初始化類仍在加載多次。 –

+0

你的子元素消失了嗎?如果沒有批量元素,您可能必須使用「一次」值而不是「perBatch」 – Heri

+0

我剛剛粘貼了主線...... 位於標記內。 –

相關問題