【问题标题】:junit5 MethodSource in nested class嵌套类中的 junit5 MethodSource
【发布时间】:2018-06-04 15:35:58
【问题描述】:

我正在使用 junit5,我想在嵌套类中创建参数化测试。例如:

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 **/
}

问题是@MethodSource要求指定的方法必须是static。但是 Java 不允许在非静态内部类中使用静态方法。如果我创建类 Cost static 那么它不会被 junit 收集。

我应该怎么做才能解决这个问题?

【问题讨论】:

    标签: java junit junit5


    【解决方案1】:

    @TestInstance(PER_CLASS)

    您可以选择“每个类一个测试实例”模式用@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)
                );
            }
        }
    
    }
    

    使用此模式时,每个测试类都会创建一个新的测试实例。

    ArgumentsProvider

    或者您可以从MethodSource 切换到ArgumentsProvider

    我修改了您的示例以查看它是否可以在本地编译和运行:

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

    更多详情http://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests

    【讨论】:

    • 我认为在这种情况下测试数据和测试在逻辑上被吐了。我不确定这是个好主意。
    • 添加了第二个解决方案,a) 允许使用非静态方法源,b) 将测试数据和逻辑就地绑定。警告:使用此模式时,每个测试类将创建一个新的测试实例。
    • 让我很恼火的是,Java 不会让我在我的内部非静态类中有一个静态方法。对我来说似乎有点武断。
    【解决方案2】:

    基于JUnit 5.2.0 的另一个变体是这样的。

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

    }

    【讨论】:

    • 您可以通过映射 Stream 来替换 Arguments.of,而不是将其添加到所有元素 .map(Arguments::of);
    【解决方案3】:

    这个游戏有点晚了,但是...

    您可以在外部类中将提供程序实现为静态的。然后,在@MethodSource 中,您只需提供参数的完全限定名称(即 com.biz.pckg.colors)。

    这在 JUnit 用户指南中有记录。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    • 2013-09-04
    相关资源
    最近更新 更多