同一@ParameterizedTest同时使用@MethodSource和@EnumSource报错
问题产生原因
JUnit 5参数化测试原生不支持同时叠加多个数据源注解实现参数合并/笛卡尔积生成。当在同一个测试方法上标注多个数据源注解(比如本例的@MethodSource和@EnumSource)时,框架不会把两个数据源提供的参数拼到一起传给测试方法,而是会独立遍历每个数据源,把每个数据源单独产出的参数列表按顺序匹配测试方法的形参:
- 本例中
@MethodSource提供的每组参数只有3个值:BigDecimal类型的金额、Boolean类型的富裕标识、Int类型的身高,正好对应测试方法的后三个形参,但测试方法第一个形参是CountryDetails类型,框架会直接把MethodSource返回的第一个参数(BigDecimal实例)映射到第一个形参位置,自然无法完成类型转换,抛出参数解析异常。 - 就算调整MethodSource的参数顺序避开这个报错,后续遍历
@EnumSource时,该数据源每组只提供1个CountryDetails类型的参数,凑不齐测试方法要求的4个入参,依然会抛出参数解析异常。
正确实现方案
如果预期效果是把@EnumSource筛选出的4个枚举值,和@MethodSource定义的2组基础参数做笛卡尔积(总共生成4*2=8个测试用例,覆盖所有枚举值+基础参数的组合),只需要保留@MethodSource注解,在方法源内部手动实现参数组合即可,不需要叠加@EnumSource,参考代码如下:
@ParameterizedTest @MethodSource("methodTest") fun `test name`( country: CountryDetails, amount: BigDecimal, rich: Boolean, hight: Int, ) { // 编写测试逻辑 } @JvmStatic fun methodTest(): Stream<Arguments> { // 对应原@EnumSource的筛选规则:只取A/B/C/D四个枚举值 val targetCountries = listOf(CountryDetails.A, CountryDetails.B, CountryDetails.C, CountryDetails.D) // 原@MethodSource定义的基础参数组 val baseArgs = listOf( Triple(BigDecimal(800), false, 50), Triple(BigDecimal(900), true, 50) ) // 手动生成笛卡尔积,把枚举值拼到每组参数的第一位,匹配方法形参顺序 return targetCountries.flatMap { country -> baseArgs.map { (amount, rich, height) -> Arguments.of(country, amount, rich, height) } }.stream() }
如果需求不是笛卡尔积,而是想把两个数据源各自的测试用例合并到同一个测试方法下顺序执行,也需要在同一个@MethodSource中补全所有用例的参数,保证每一组返回的Arguments都覆盖测试方法的全部4个形参,不能靠叠加多个数据源注解实现。
注意:JUnit 5所有内置数据源注解(@ValueSource、@CsvSource、@EnumSource、@MethodSource等)都不支持叠加后自动合并参数,所有多数据源组合逻辑都需要在单一方法源中手动实现。
内容的提问来源于stack exchange,提问作者liza tawaf
相关产品推荐
相关产品推荐

