2011-07-16 73 views
26

我在JUnit中有很多測試用例。它們都需要使用相同的代碼才能在其@BeforeClass靜態方法中執行。這是一個代碼重複,我試圖擺脫它。這樣做的一個骯髒的方式是繼承。 JUnit中是否有其他機制,可能有所幫助?如何避免JUnit測試用例中的繼承?

PS。我寫了這篇關於這個主題的博客文章:http://www.yegor256.com/2015/05/25/unit-test-scaffolding.html

+0

所有'@ BeforeClasses'完全相同還是隻是共享一些代碼? –

+1

爲什麼繼承是一種骯髒的方式? –

+0

@lu,該方法是靜態的,繼承不會是最好的。 –

回答

26

JUnit組成可重用代碼(而不是從中繼承)的方式是規則。

https://github.com/junit-team/junit/wiki/Rules

這是一個愚蠢的樣品,但你會得到點。

import org.junit.rules.TestRule; 
import org.junit.runners.model.Statement; 
import org.junit.runner.Description; 

public class MyTestRule implements TestRule { 
    @Override 
    public Statement apply(final Statement statement, Description description) { 
    return new Statement() { 
     public void evaluate() throws Throwable { 
     // Here is BEFORE_CODE 
     try { 
      statement.evaluate(); 
     } finally { 
      // Here is AFTER_CODE 
     } 
     } 
    }; 
    } 
} 

然後,您可以使用您的TestRule這樣的:

import org.junit.Rule; 

public class MyTest { 
    @Rule 
    public MyTestRule myRule = new MyTestRule(); 
} 

BEFORE_CODE和AFTER_CODE然後將圍繞每個測試方法執行。

如果你需要爲每個班級只運行一次你的代碼,用你的TestRule作爲@ClassRule:

import org.junit.ClassRule; 

public class MyTest { 
    @ClassRule 
    public static MyTestRule myRule = new MyTestRule(); 
} 

現在,BEFORE_CODEAFTER_CODE將圍繞每個測試類的執行。

@Rule字段不是靜態的,@ClassRule字段是。

@ClassRule也可以在套件中聲明。

請注意,您可以在單個測試類中聲明多個規則,這就是如何在測試套件,測試類和測試方法級別組成測試生命週期的方式。

規則是你在你的測試類中實例化的對象(靜態或不靜態)。如果需要,你可以添加構造器參數。

HTH

4

如果方法是某種實用工具,那麼使用靜態方法將其分離出來,並在@BeforeClass中調用該方法。

我強調這樣一個事實,即不要僅僅因爲它解決了你的問題而使用繼承,而是在你的類層次結構中使用它。

0

如果每個類都需要有一個@BeforeClass標註的方法是正是一樣每隔,然後繼承不覺得我錯了。如果這些初始化方法中的每一個都簡單地共享代碼,則可以使用某種共享行爲創建一個TestUtil類,並調用每個@BeforeClass方法的此共享行爲。

1

靜態方法不會被繼承,因此默認情況下繼承不是一個選項。如果你的意思是你將方法移動到一個共同的父類,那麼這看起來是一個糟糕的選擇,因爲你只能得到一個父Java。某種測試支持類似乎更合適。您也可能看到需要parameterized test

0

我認爲如果這些類有「is-a」的關係,繼承是合理的。

如果基類是MyBeforeClass定義@BeforeClass方法,和MyTestClass1「是一個」 MyBeforeClassMyTestClass1 extends MyBeforeClass是OK。

0

根據設置代碼的性質,您可以將所有測試放在測試suite中,並讓設置代碼在那裏運行。缺點是你不能單獨運行測試(因爲測試取決於設置代碼)。

1

在這種情況下,繼承沒有任何問題,它實際上是避免在每個子類中重複此代碼的唯一方法。 @BeforeClass方法必須在JUnit中聲明爲靜態的事實是不幸的,但這不應該阻止你。擴展該類,並且您可以自動運行初始化代碼,而無需執行任何操作。

+0

不,它不是唯一的方法,看到其他答案,並且由於靜態方法不被繼承,它是否是一種方式是可疑的。你試過了嗎? – EJP

2

您可以創建測試運行

public class MyTestRunner extends BlockJUnit4ClassRunner { 
    @Override 
    protected Object createTest() throws Exception { 
    Object test = super.createTest(); 
    doStuff(); 
    } 

    public void doStuff(){ 
    //common code 
    } 
} 


@RunWith(MyTestRunner.class) 
public class MyTest1{ 
    @Test 
    public void test1(){ 
     //test method 
    } 
} 
-2

這是測試代碼,這並不意味着對重型再利用。不要過度設計。不要應用你所知道的所有設計模式。對於測試代碼,規則是不同的。