junitjunit5junit-jupiterparameterized-unit-testparameterized-tests

Repeated parameterized test with JUnit 5 / Jupiter


I want to repeatedly execute the following test class:

class Test {

    static Foo foo;

    @BeforeAll
    static void setUpAll() {
        foo = generateRandomFoo();
    }

    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4})
    void testBar(int i) {
        assertThat(foo.bar(i))
                .hasSize(i);
    }

    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4})
    void testQux(int i) {
        assertThat(foo.qux(i))
                .contains(i);
    }
}

I tried using annotation @ParameterizedTest on the method together with @RepeatedTest, but they cannot be used together. Even if they could, it still wouldn't do what I need it to, because I need the initialization of foo in setUpAll to happen between repetitions, and the parameterized invocations should happen within a repetition (with the same value of foo).

Here's what I need:

Is there any way to do this in JUnit 5 (Jupiter)?


Solution

  • Starting with JUnit Jupiter 5.13 you may use @ParameterizedClass to achieve your goal.

    https://junit.org/junit5/docs/snapshot/user-guide/#writing-tests-parameterized-tests

    Parameterized classes make it possible to run all tests in test class, including Nested Tests, multiple times with different arguments. They are declared just like regular test classes and may contain any supported test method type (including @ParameterizedTest) but annotated with the @ParameterizedClass annotation.

    For example like this:

    @ParameterizedClass
    @MethodSource("repeater")
    record RepeatedParameterizedTests(Object foo) {
      static Stream<Object> repeater() {
        return Stream.generate(Object::new).limit(3);
      }
    
      @ParameterizedTest
      @ValueSource(ints = {1, 2, 3, 4})
      void testBar(int i) {}
    
      @ParameterizedTest
      @ValueSource(ints = {1, 2, 3, 4})
      void testQux(int i) {}
    }