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

2022-08-31 15:52:58

我有一个接口,其实现包括Singly Linked List,Doubly,Circular 等。我为Singly编写的单元测试应该对Double的大部分内容以及Circular和任何其他新的接口实现都有好处。因此,JUnit是否提供了一些内置的东西,让我有一个JUnit测试并针对不同的实现运行它,而不是为每个实现重复单元测试?List

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


答案 1

我可能会避免JUnit的参数化测试(恕我直言,这些测试非常笨拙地实现),而只是制作一个抽象的测试类,它可以被测试实现继承: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(){ /* ... */ }

}

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

class SinglyLinkedListTest extends ListTestBase<SinglyLinkedList> {

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

}

class DoublyLinkedListTest extends ListTestBase<DoublyLinkedList> {

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

}

这样做的好处是(而不是创建一个测试类来测试所有实现),如果想要使用一个实现测试一些特定的角落情况,则可以向特定的测试子类添加更多测试。


答案 2

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

  • 向测试夹具添加注释@RunWith(value = Parameterized.class)
  • 创建一个返回的方法,用 、对其进行注释,然后将 、 、 等 放入该集合中public staticCollection@ParametersSinglyLinkedList.classDoublyLinkedList.classCircularList.class
  • 向测试夹具添加一个构造函数,该构造函数采用 : ,并将 存储在实例变量中Classpublic MyListTest(Class cl)ClasslistClass
  • 在方法 或 中使用setUp@BeforeList testList = (List)listClass.newInstance();

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


推荐