为接口的多个实现编写单个单元测试

Chr*_*ney 51 java junit unit-testing junit4 junit-runner

我有一个接口,List其实现包括单链接列表,双重,循环等.我为Singly编写的单元测试应该对大多数双重以及循环和接口的任何其他新实现都有好处.因此,JUnit不是为每个实现重复单元测试,而是提供内置的东西,让我有一个JUnit测试并针对不同的实现运行它?

使用JUnit参数化测试我可以提供不同的实现,如Singly,doublely,circular等,但是对于每个实现,相同的对象用于执行类中的所有测试.

gus*_*afc 53

我可能会避免使用JUnit的参数化测试(IMHO非常笨拙地实现),只需创建一个List可以通过测试实现继承的抽象测试类:

public abstract class ListTestBase<T extends List> {

    private T instance;

    protected abstract T createInstance();

    @Before 
    public void setUp() {
        instance = createInstance();
    }

    @Test
    public void testOneThing(){ /* ... */ }

    @Test
    public void testAnotherThing(){ /* ... */ }

}
Run Code Online (Sandbox Code Playgroud)

然后,不同的实现获得自己的具体类:

class SinglyLinkedListTest extends ListTestBase<SinglyLinkedList> {

    @Override
    protected SinglyLinkedList createInstance(){ 
        return new SinglyLinkedList(); 
    }

}

class DoublyLinkedListTest extends ListTestBase<DoublyLinkedList> {

    @Override
    protected DoublyLinkedList createInstance(){ 
        return new DoublyLinkedList(); 
    }

}
Run Code Online (Sandbox Code Playgroud)

这样做的好处(而不是制作一个测试所有实现的测试类)是,如果有一些特定的极端情况,你想用一个实现测试,你可以只添加更多的测试到特定的测试子类.

  • 谢谢你的答案,它比Junit Paramterized测试更优雅,我可能会用它.但我必须坚持使用dasblinkenlight的答案,因为我正在寻找一种方法,使用Junit的参数化测试 (2认同)
  • 我实际上会使用测试接口,而不是用于基本测试的公共抽象类(https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-interfaces-and-default-methods )来自junit5,正是为了这个目的 (2认同)

das*_*ght 35

使用JUnit 4.0+,您可以使用参数化测试:

  • @RunWith(value = Parameterized.class)在测试夹具中添加注释
  • 创建一个public static方法返回Collection,带有注释它@Parameters,并把SinglyLinkedList.class,DoublyLinkedList.class,CircularList.class等进入该集合
  • 将测试夹具的构造函数添加到Class:public MyListTest(Class cl),并将其存储Class在实例变量中listClass
  • setUp方法或@Before,使用List testList = (List)listClass.newInstance();

通过上述设置,参数化运行器将为MyListTest您在@Parameters方法中提供的每个子类创建测试夹具的新实例,从而为您需要测试的每个子类执行相同的测试逻辑.

  • 该解决方案的一个问题是传递的对象需要周围的逻辑,例如释放资源.目前还不清楚这段代码的位置,因为它没有等同于`@ After`或`@ AfterClass`.此外,我想知道这是否是滥用`@ Parameterized` - 我想知道它是否应该严格用于简单的参数传递给被测试的类,而不是类本身.我个人有时会使用这种方法,但我认为它有点受限. (3认同)