【问题标题】:JUnit5: Test multiple classes without repeating codeJUnit5:测试多个类而不重复代码
【发布时间】:2017-11-24 13:50:12
【问题描述】:

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

有提供基本功能(pop、push、peek等)的“Stack”界面。然后我有 2 个具体的类,一个借助数组,一个借助链表(在这种情况下如何并不重要)。

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

我已经尝试过“ParameterizedTests”,但没有任何进展。

我会很高兴得到帮助!

【问题讨论】:

  • @ParameterizedTest 应该是要走的路——你试试有什么问题?
  • 我现在知道如何正确使用它了。我只是没有为 JUnit5 找到任何好的教程。
  • 也许发布一个最小的代码示例,以便我们可以检查问题出在哪里?
  • 我认为如果你能给我一些代码语法就足够了,它显示了我如何使用 @ParameterizedTest 的两个类。

标签: java junit5


【解决方案1】:

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

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();
    }
}

【讨论】:

    【解决方案2】:

    我不知道@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;
      }
    }
    

    【讨论】:

    • 非常感谢,但是代码运行时出错:“java.lang.AbstractMethodError”
    • Err... 请问您有完整的堆栈跟踪吗?另外,你如何运行测试?我刚刚在 Eclipse 中运行它并且运行良好。
    • 我更新了我的帖子并添加了错误,然后我在 IntelliJ 中运行了它。
    • @Joey:我明白了,您可能遇到了 IntelliJ 的错误 - 请检查您的 JUnit 和 IntelliJ 版本,this 是 IntelliJ 中对 JUnit 5 M4 支持的更新。
    • 我更新了 JUnit 和 IntelliJ,现在出现了不同的错误。我更新了我的帖子并添加了新错误。
    【解决方案3】:

    在给定接口类型作为参数的情况下,创建一个执行测试的私有方法

    private void testStack(Stack stack) {...}
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-06
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多