2012-06-22 93 views
2

我試圖寫一些廣泛使用的接口測試合同:爪哇 - 合同測試

線沿線的:

public abstract class MyInterfaceContractTest extends TestCase { 

    private MyInterface _toTest; 

    public void setUp(){ 
    _toTest = getTestableImplementation(); 
    } 

    protected abstract MyInterface getTestableImplementation(); 

    public void testContract(){ 

    } 
} 

......還有......

public class MyInterfaceImplementationTest extends MyInterfaceContractTest { 

    protected MyInterface getTestableImplementation(){ 
    return new MyInterfaceImplementation(...); 
    } 
} 

但是,我希望能夠測試MyInterfaceImplementation的多個實例。在我的用例中,這是一個包含數據集合的不可變對象(訪問器按照接口MyInterface指定),它可能爲空,或者有少量數據,甚至有大量數據。

所以問題是,我如何測試我的實現的多個實例?

目前,我必須初始化實現以將其傳遞到抽象合約測試中。一種方法是爲每個實現提供多個測試類,其中每個測試類都測試該實現的特定實例 - 但這似乎有點龐大而且難以跟蹤。

FWIW,我使用JUnit 3

+0

JUnit 3是古老的。爲什麼不使用JUnit 4? –

+0

@DonRoby - 這會對解決我的問題有所幫助嗎?我正在使用JUnit 3,因爲這是我們的單元測試當前寫入的內容,並且從未優先升級到JUnit 4. – amaidment

+0

http://junit.sourceforge.net/javadoc/org/junit/runners/Parameterized。 html可能會有用。 –

回答

2

如果我已經正確理解您的需求,您希望運行相同接口的多個實現的相同測試方法或方法。

我不知道如果你願意升級到JUnit 4中如何在JUnit的3

做到這一點非常漂亮,這可以通過使用一個參數化測試來完成。

對於運行在接口上的兩個實現一個單一的測試方法的簡單的例子,你的測試代碼可能是這個樣子:

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.junit.runners.Parameterized; 

import java.util.Arrays; 
import java.util.Collection; 

import static junit.framework.Assert.assertEquals; 

// Tell JUnit4 to run it as a parametrized test. 
@RunWith(Parameterized.class) 
public class MyInterfaceContractTest { 

    private MyInterface _toTest; 

    // Load the test data into your test instance via constructor 
    public MyInterfaceContractTest(MyInterface impl) { 
     this._toTest = impl; 
    } 

    // Supply the test data, in this example just the two implementations you want to test. 
    @Parameterized.Parameters 
    public static Collection<Object[]> generateData() { 
     return Arrays.asList(new Object[]{new MyInterfaceImpl1()}, new Object[]{new MyInterfaceImpl2()}); 
    } 

    @Test 
    public void testContract(){ 
     // assert whatever, using your _toTest field 
    } 
} 

運行這個測試時,JUnit會運行測試兩次,調用在參數列表中具有連續條目的構造函數。

如果你有更復雜的東西,比如對不同實現不同的期望,數據生成可以返回包含多個元素的對象數組列表,然後構造將採取相應的多個參數。

如果您需要重新初始化測試方法之間的測試對象,你可能也想使用我this related question描述的伎倆。

我相信類似的事情在TestNG,這可能是你的升級路徑的另一個選擇是可能的。

+0

超級 - 謝謝。我花了幾天的時間決定切換到Junit 4,但這是一個很好的解決方案。 – amaidment

2

一般的方法是使用抽象類的「可驗證」的子類來測試抽象類的所有功能於一體的測試。然後爲每個具體實現編寫一個單獨的測試,測試具體類中定義/實現的方法(不要重新測試具體類中的功能)。

+0

+1:這對於抽象類來說絕對是一個很好的策略,其中定義了一些功能。對於一個普通接口的多個實現,你可能最好使用參數化測試。 –

+0

我這樣做測試實現沒有額外的方法了。失敗消息比使用參數化測試更好,並且更容易選擇性地對單個實現運行測試。 –