【问题标题】:Dynamically changing @MethodSource in abstract class from a @ParameterizedTest (Jupiter-Junit 5)从@ParameterizedTest(Jupiter-Junit 5)动态更改抽象类中的@MethodSource
【发布时间】:2022-02-03 16:36:18
【问题描述】:

我目前正在编写与 GET 请求相关的单元测试,下面是一个采用泛型 E 的参数化测试。

abstract class AbstractEntityTest< E extends Entity > {

@ParameterizedTest( name = "[{index}]: {2}" )
@MethodSource( "RoleDataProvider#provideIntArgsToTest" )
void testIntRequestsThatReturnSingle( String fileName, Integer requestParam, String testName, int index )
         // do something
    }
}

我要做的是在运行时根据 E 的实际类型动态更改方法源。

例子:

public class AnimalTest extends AbstractEntityTest< Animal > {
... }

这里 E 是 Animal 类型,所以我想将 @MethodSource 更改为

@MethodSource( "AnimalDataProvider#provideIntArgsToTest" )

有什么办法吗?我一直在寻找几个小时无济于事......

【问题讨论】:

    标签: java java-8 assertion junit-jupiter parameterized-tests


    【解决方案1】:

    恐怕这在 Java 中是不可能的。 Java 是一种强静态类型语言,这意味着对象无法更改其类型,并且在编译期间会进行类型检查。

    Java 使用擦除实现泛型,这意味着编译器会将您的绑定类型参数E 替换为绑定类Entity,(描述为here)。

    你想达到什么目的?如果你想避免重复,你可以将共享逻辑分组到一个方法中,并称之为@BeforeEach

    编辑:明白了,我想我知道你的意思,为响应欢呼。您是否尝试过在子测试类中指定这一点?

    我尝试使用相同的概念,但使用 NumberIntegerDouble。这是我得到的: AbstractTest.java

    public abstract class AbstractTest<E extends Number> {
    
        void testIntRequestsThatReturnSingle(Number i){
            System.out.println(i);
            //doing the same stuff here but with the different data sources
        }
    
        public static IntStream intProvider() {
            return IntStream.range(0, 10);
        }
    
        public static DoubleStream doubleProvider() {
            return DoubleStream.of(0.0,1.1,2.2);
        }
    }
    

    一个孩子IntTest.java班级:

    public class IntTest extends AbstractTest<Integer>{
        @ParameterizedTest
        @MethodSource( "intProvider" )
        public void intTest(Number i){
            this.testIntRequestsThatReturnSingle(i);
        }
    }
    

    另一个孩子DoubleTest.java班级:

    public class DoubleTest extends AbstractTest<Integer>{
        @ParameterizedTest
        @MethodSource( "doubleProvider" )
        public void doubleTest(Number i){
            this.testIntRequestsThatReturnSingle(i);
        }
    }
    

    这样您可以最​​大限度地减少重复并确保为正确的类调用正确的方法(没有任何可怕的强制转换)。这是否符合您的要求?

    【讨论】:

    • 正如你所说,主要是为了避免代码重复。有一种解决方法可以通过反射获取 E 的类型: ``` Class getGenericClass() { return ( Class ) ( ( ParameterizedType ) getClass().getGenericSuperclass() ).getActualTypeArguments()[ 0 ] ; }```它给了我一个警告,但它有效我想要做的是在我的通用类中编写所有通用测试,但我必须覆盖我的子类中的一个方法才能让它工作基本上测试工作,我只需要更改提供给它的数据即可测试所有内容。
    • 嘿,谢谢,差不多了!几个小时前我想出了一个类似的解决方案,但我真的希望我能弄乱@MethodSource 注释哈哈。我做了一些研究,因为注释是在编译时评估的,所以不可能在运行时改变它们。再次感谢:)
    猜你喜欢
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 2019-06-08
    • 2016-03-12
    • 2018-07-05
    • 1970-01-01
    相关资源
    最近更新 更多