JUnit5:测试多个类而不重复代码

时间:2017-11-24 13:50:13

标签: java junit5

我在Java中构建了自己的堆栈实现,看起来像这样:

接口“Stack”提供基本功能(pop,push,peek等)。然后我有两个具体的类,一个是数组的帮助,另一个是链表(在这种情况下,如何不重要)。

现在我的问题:我想用JUnit5测试它,因为你不能实例化一个接口,我必须为带有数组的类测试一次,对于带有链表的类测试一次,所以代码是不必要的长。有没有办法可以测试界面的所有功能或类似的东西?因为如果现在添加了第三个实现,我将不得不重新编写它。

我已经尝试了'ParameterizedTests',但我没有取得任何进展。

我很乐意帮忙!

3 个答案:

答案 0 :(得分:1)

创建一个私有方法,在给定接口类型作为参数

的情况下执行测试
private void testStack(Stack stack) {...}

然后在单元测试中调用它:

@Test
public void testImplementations() {
     testStack(new ListStack());
     testStack(new LinkedListStack());
}

答案 1 :(得分:1)

我不知道您遇到的@ParameterizedTest有什么问题,但正如您所要求的,这是一个非常通用的测试示例,可能对您的测试有用:

import static org.junit.jupiter.api.Assertions.assertEquals;  
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
...

public static Stream<Arguments> provideStacks() {
  return Stream.of(
      Arguments.of(new ArrayStack()),
      Arguments.of(new LinkedStack())
  );
}

@ParameterizedTest
@MethodSource("provideStacks")
public void test(Stack stack) {
  stack.push(1);
  assertEquals(1, stack.pop());
}

public interface Stack {
  void push(int i);
  int pop();
}

public static final class ArrayStack implements Stack {
  @Override
  public void push(int i) {
  }

  @Override
  public int pop() {
    return 1;
  }
}

public static final class LinkedStack implements Stack {
  @Override
  public void push(int i) {
  }

  @Override
  public int pop() {
    return 1;
  }
}

答案 2 :(得分:1)

Test Interfaces将是另一种可能性。您将测试定义为接口的默认方法,并在每个堆栈实现时实现一次接口。每个实现都可以添加其他测试等。

interface StackContractTests {

    Stack newEmptyStack();

    @Test
    default void popsWhatWasLastPushed() {
        Stack stack = newEmptyStack();
        stack.push("foo");
        assertEquals("foo", stack.pop());
    }

    @Test
    default void cannotPopFromEmptyStack() {
        Stack stack = newEmptyStack();
        assertThrows(EmptyStackException.class, stack::pop);
    }
}

public class ArrayListBasedStackTests implements StackContractTests {
    @Override
    public Stack newEmptyStack() {
        return new ArrayListBasedStack();
    }
}

public class LinkedListBasedStackTests implements StackContractTests {
    @Override
    public Stack newEmptyStack() {
        return new LinkedListBasedStack();
    }
}