2012-06-18 109 views
8

我想運行不同的接口實現相同的JUnit測試。我發現與@Parameter選項很好的解決方案:用同樣的測試測試多接口的實現 - JUnit4

public class InterfaceTest{ 

    MyInterface interface; 

    public InterfaceTest(MyInterface interface) { 
    this.interface = interface; 
    } 

    @Parameters 
    public static Collection<Object[]> getParameters() 
    { 
    return Arrays.asList(new Object[][] { 
     { new GoodInterfaceImpl() }, 
     { new AnotherInterfaceImpl() } 
    }); 
    } 
} 

此測試將被運行兩次,先用GoodInterfaceImpl然後用AnotherInterfaceImpl類。但問題是我需要爲大多數測試用例創建一個新對象。一個簡單的例子:

@Test 
public void isEmptyTest(){ 
    assertTrue(interface.isEmpty()); 
} 

@Test 
public void insertTest(){ 
    interface.insert(new Object()); 
    assertFalse(interface.isEmpty()); 
} 

如果isEmptyTestinsertTest後運行失敗。

是否有與實施的新實例自動運行測試用例每一個選項?

BTW:實現明確的()復位() - 方法的接口是不是一個真正的選擇,因爲我不需要它的生產代碼。

+0

我建議尋找到依賴注入。這裏是一篇關於如何使用它來完成你正在尋找的東西的小文章 http://www.javaranch.com/journal/200709/dependency-injection-unit-testing.html –

+0

感謝您的快速回答!但是這篇文章描述瞭如何打破一個接口的依賴關係。我想測試接口(而不是使用接口的類,或者根據文章說話:我想測試遠程服務器場(分別是引擎)而不是農場servlet [分別是汽車])。 –

回答

4

創建一個工廠接口和實現,可能只在您的測試層次結構中,如果您不需要生產中的這樣的東西,並且使getParameters()返回工廠列表。

然後,您可以調用工廠中的@Before帶註釋的方法,以獲取您的實際類的每個測試方法運行的新實例。

+0

非常感謝!這是一個聰明的解決方案,我會實現:) –

5

這裏是與模板方法模式的另一種方法:

的面向接口測試進入基類:

public abstract class MyInterfaceTest { 

    private MyInterface myInterface; 

    protected abstract MyInterface makeContractSubject(); 

    @Before 
    public void setUp() { 
     myInterface = makeContractSubject(); 
    } 

    @Test 
    public void isEmptyTest(){ 
     assertTrue(myInterface.isEmpty()); 
    } 

    @Test 
    public void insertTest(){ 
     myInterface.insert(new Object()); 
     assertFalse(myInterface.isEmpty()); 
    } 
} 

對於每個具體的類,定義一個具體的測試類:

public class GoodInterfaceImplTest extends MyInterfaceTest { 

    @Override 
    protected MyInterface makeContractSubject() { 
     // initialize new GoodInterfaceImpl 
     // insert proper stubs 
     return ...; 
    } 

    @Test 
    public void additionalImplementationSpecificStuff() { 
     ... 
    } 
} 

在@Parameter微弱優勢是在測試失敗時,你得到報告的具體測試類的名稱,讓你馬上知道哪個實現失敗。

順便說一下,爲了這個方法在所有的工作中,接口必須在某種程度上允許測試僅由接口方法設計。這意味着基於狀態的測試 - 您無法在基本測試類中驗證模擬。如果您需要在特定於實現的測試中驗證模擬,那麼這些測試必須進入具體測試類。

+0

+1另一個好方法:)但是關於類名稱,現在有可能(JUnit> = 4.11)給測試賦予不同的名稱,儘管它不是很方便使用 - > http://stackoverflow.com/questions/650894/changing-names-of-parameterized-tests(s。最高評分的答案,而不是接受的)。不過,我喜歡你的解決方案,因爲你可以將實現特定的測試添加到派生測試類中。有些事情我需要額外的課程。 –

1

萬一有人達到這裏(像我一樣),尋找.NET測試相同接口的多個實現,你可以看到,我用在項目中的一個方法之一here

以下就是我們在短期

遵循了相同的測試項目中的dll運行使用vstest.console兩次,通過設置環境變量。在測試中,(在程序集初始化或測試初始化​​中)根據環境變量值將適當的實現註冊到IoC容器中。

0

JUnit中5,你可以這樣做:

@ParameterizedTest 
@MethodSource("myInterfaceProvider") 
void test(MyInterface myInterface) {} 

static Stream<MyInterface> myInterfaceProvider() { 
    return Stream.of(new ImplA(), new ImplB()); 
} 

interface MyInterface {} 

static class ImplA implements MyInterface {} 

static class ImplB implements MyInterface {}