'junit5 MethodSource in nested class

I am working with junit5 and I want to create Parameterized Test in nested class. For example:

class CardTest {

    @Nested
    class Cost {
        Stream<Arguments> cards() {
            return Stream.of(
                    Arguments.of(Card.common(0, Color.RED), 0),
                    /** Other Data **/
                    Arguments.of(Card.choseColor(), 50)
            );
        }

        @MethodSource("cards")
        @ParameterizedTest
        void cardCost(Card card, int cost) {
            assertThat(card.cost())
                    .isEqualTo(cost);
        }
    }
    /** Some other nested classes or simple methods **/
}

The problem is @MethodSource required that specified method must be static. But Java not allowed static method in non-static inner classes. If I create class Cost static then it won't be collected by junit.

What should I do to resolve this issue?



Solution 1:[1]

@TestInstance(PER_CLASS)

You may select the "single test instance per class" mode annotating the nested class with @TestInstance(TestInstance.Lifecycle.PER_CLASS):

class ColorTest {

    @Nested
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    class Inner {

        @ParameterizedTest
        @MethodSource("colors")
        void blue(Color color, int blue) {
            Assertions.assertEquals(color.getBlue(), blue);
        }

        Stream<Arguments> colors() {
            return Stream.of(
                    Arguments.of(Color.BLACK, 0),
                    Arguments.of(Color.GRAY, 128),
                    Arguments.of(Color.BLUE, 255)
            );
        }
    }

}

When using this mode, a new test instance will be created once per test class.

ArgumentsProvider

Or you may switch from a MethodSource to an ArgumentsProvider.

I modified your example to see if it compiles and runs locally:

class ColorTest {

    static class Blues implements ArgumentsProvider {

        @Override
        public Stream<Arguments> provideArguments(ExtensionContext context) {
            return Stream.of(
                    Arguments.of(Color.BLACK, 0),
                    Arguments.of(Color.GRAY, 128),
                    Arguments.of(Color.BLUE, 255)
            );
        }
    }

    @Nested
    class Inner {

        @ParameterizedTest
        @ArgumentsSource(Blues.class)
        void blue(Color color, int blue) {
            Assertions.assertEquals(color.getBlue(), blue);
        }
    }

}

More details at http://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests

Solution 2:[2]

Another variation based on JUnit 5.2.0 is this.

class ColorTest {

public static Stream<Arguments> provideColors() {
    return Stream.of(
            Arguments.of(Color.BLACK, 0),
            Arguments.of(Color.GRAY, 128),
            Arguments.of(Color.BLUE, 255)
    );
}

@Nested
class Inner {

    @ParameterizedTest
    @MethodSource("com.domain.ColorTest#provideColors")
    void blue(Color color, int blue) {
        Assertions.assertEquals(color.getBlue(), blue);
    }
}

}

Solution 3:[3]

A bit late to this game, but...

You can implement the provider, as a static, in the outer class. Then, in @MethodSource, you simply need to provide the fully qualified name of the parameter (i.e., com.biz.pckg#colors).

This is documented in the JUnit user guide.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 jpenna