JUnit-共享不同实现的测试

时间:2018-09-18 16:00:05

标签: java unit-testing junit junit4 junit5

我正在寻找一种最易读的方式来共享接口的不同实现的测试。

关于此主题的最受欢迎但相当古老的问题是- Writing a single unit test for multiple implementations of an interface

对于上述问题,给出了2个主要且不同的答案-

  1. 参数化测试。
  2. 测试继承。

两个答案我都不满意。

  1. 参数化测试-答案不包括如何参数化每个子类的代码示例。另外,我个人很难进行参数化测试,我发现API根本不直观。

  2. 我总是担心继承会过度使用,而且我不确定测试继承是否是一种好习惯。

我想知道2018年该问题的最佳答案是什么。

2 个答案:

答案 0 :(得分:1)

参数化测试似乎仍然是此类用例的教科书解决方案。 JUnit Jupiter's syntax确实使它更加优雅。 API更加清晰,恕我直言(测试有参数,并且注释显示了它们的来源):

public class ListTest {

    public static Stream<List<String>> lists() {
        return Stream.of(new ArrayList<>(), new LinkedList<>());
    }

    @ParameterizedTest
    @MethodSource("lists")
    public void testAdd(List<String> list) {
        list.add("xyz");
        assertEquals(1, list.size());
        assertFalse(list.isEmpty());
        assertEquals("xyz", list.get(0));
    }
}

答案 1 :(得分:0)

可能不是最类似于Java的,但是您可以遵循表驱动的测试格式。使用本地类,可以使测试保持最高可读性,并使上下文尽可能接近真实测试。

注意:这与@RunWith(Parameterized.class)

的基础高级方法非常相似
// Assuming Animal interface has a `public boolean canDance()`

@Test
public void TestAnimalCanDance() {
    class Tester {
        String errMsgFmt = "%s failed the test";
        boolean expected;
        Animal animal;
        public Tester(boolean expected, Animal animal) {
            this.expected = expected;
            this.animal = animal;
        }
    }

    Tester dog = new Tester(true, new Dog());
    Tester cat = new Tester(false, new Cat());
    Tester monkey = new Tester(false, new Monkey());
    Tester[] tests = Arrays.asList(dog, cat, monkey);

    for (Tester t: tests) {
        boolean actual = t.canDance();
        assertTrue(actual == t.expected);
    }
}