测试实现相同接口的类的最佳方法

时间:2014-09-04 15:53:33

标签: java junit junit4

因此,例如我有一些实现List<T>接口的类。如何测试它们 - 它们是否正确实现了方法?

现在我只看到一种方法:

public class MyListImplementationsTest {
    private Collection<List<Integer>> listImplementations;

    @BeforeClass
    public static void setUp() throws Exception {
        listImplementations = Arrays.asList(
            new QuickList<Integer>(), new EfficientMemoryList<Integer>()
        );
    }

    @Test
    public void testIsEmptyAfterCreationEmptyList() {
        // Use forEachList(handler) in order to not iterate
        // the lists manually every time.
        // May be there is no need to do so,
        // because using <<for (item : items)>> instead of
        // iterating using index prevents from OutOfBounds errors
        forEachList(new OnEachListHandler<Integer>() {
            @Override
            public void onEach(List<Integer> list) {
                assertTrue(list.isEmpty());
            }
        });
    }

    private <T> void forEachList(OnEachListHandler<T> handler) {
        for (List<T> each : listImplementations) {
            handler.onEach(each);
        }
    }

    private static interface OnEachListHandler<T> {
        void onEach(List<T> each);
    }
}

但在我看来,在每次测试中迭代列表都很复杂。

是否有更优雅的方法来测试在JUnit4中实现相同接口的类?

3 个答案:

答案 0 :(得分:2)

您可以创建一个基本测试,可以测试List<T>类型的任何内容以及创建此类列表的抽象方法。

然后按列表类型实施测试,扩展基本测试。 JUnit将运行基类中的测试用例以及您在扩展中定义的任何测试用例。

abstract class AbstractListTest<T> {
    protected abstract List<T> createList();

    @Test
    public void testIsEmpty() {
        List<T> list = createList();
        assertTrue(list.isEmpty());
    }

    ...more tests...
}

class QuickListTest extends AbstractListTest<QuickList> {
    protected QuickList createList() {
        return new QuickList();
    }
}

JUnit不会运行抽象基类,但会看到继承的测试并运行所有这些测试。您还可以向QuickListTest添加新测试或覆盖基类中的测试。

基本上,JUnit将接受该类,从整个继承树中查找所有公共@Test方法并运行它们。

答案 1 :(得分:0)

我会考虑将不同列表实现的测试分解为各自的测试用例,以便它们独立通过或失败。

.isEmpty()为例,如果QuickList.isEmpty()EfficientMemoryList.isEmpty()具有不同的实现,即empty概念的含义不同,那么它们是有意义的独立测试。目前,如果1个列表实现失败,则testIsEmptyAfterCreationEmptyList将失败,但其他列表实现失败。

否则,如果QuickList.isEmpty()EfficientMemoryList.isEmpty()共享相同的实现,那么您可以考虑将实现移动到公共基类,并为该基类编写测试。

仅仅因为类共享相同的接口,并不意味着他们的测试需要集中和耦合。

答案 2 :(得分:0)

单独创建每个实现的测试:QuickListTestEfficientMemoryListTest

QuickListTest.java

public class QuickListTest extends ListBase {   
    @Test
    public void shouldBeEmpty() throws Exception {   
        assertThatIsEmpty(new QuickList<Integer>());   
    }    
}

BaseList.java

public abstract class ListBase {    
    protected void assertThatIsEmpty(QuickList<Integer> actual) {
        assertThat(actual).isEmpty();
    }
}