JUnit5学习之七:参数化测试(Parameterized Tests)进阶 (2)

在这里插入图片描述

字段聚合(Argument Aggregation)

来思考一个问题:如果数据源的每条记录有多个字段,测试方法如何才能使用这些字段呢?

回顾刚才的@CsvSource示例,如下图,可见测试方法用两个入参对应CSV每条记录的两个字段,如下所示:

在这里插入图片描述


3. 上述方式应对少量字段还可以,但如果CSV每条记录有很多字段,那测试方法岂不是要定义大量入参?这显然不合适,此时可以考虑JUnit5提供的字段聚合功能(Argument Aggregation),也就是将CSV每条记录的所有字段都放入一个ArgumentsAccessor类型的对象中,测试方法只要声明ArgumentsAccessor类型作为入参,就能在方法内部取得CSV记录的所有字段,效果如下图,可见CSV字段实际上是保存在ArgumentsAccessor实例内部的一个Object数组中:

在这里插入图片描述


4. 如下图,为了方便从ArgumentsAccessor实例获取数据,ArgumentsAccessor提供了获取各种类型的方法,您可以按实际情况选用:

在这里插入图片描述

下面的示例代码中,CSV数据源的每条记录有三个字段,而测试方法只有一个入参,类型是ArgumentsAccessor,在测试方法内部,可以用ArgumentsAccessor的getString、get等方法获取CSV记录的不同字段,例如arguments.getString(0)就是获取第一个字段,得到的结果是字符串类型,而arguments.get(2, Types.class)的意思是获取第二个字段,并且转成了Type.class类型:

@Order(18) @DisplayName("CsvSource的多个字段聚合到ArgumentsAccessor实例") @ParameterizedTest @CsvSource({ "Jane1, Doe1, BIG", "John1, Doe1, SMALL" }) void argumentsAccessorTest(ArgumentsAccessor arguments) { Person person = new Person(); person.setFirstName(arguments.getString(0)); person.setLastName(arguments.getString(1)); person.setType(arguments.get(2, Types.class)); log.info("argumentsAccessorTest [{}]", person); }

上述代码执行结果如下图,可见通过ArgumentsAccessor能够取得CSV数据的所有字段:

在这里插入图片描述

更优雅的聚合

前面的聚合解决了获取CSV数据多个字段的问题,但依然有瑕疵:从ArgumentsAccessor获取数据生成Person实例的代码写在了测试方法中,如下图红框所示,测试方法中应该只有单元测试的逻辑,而创建Person实例的代码放在这里显然并不合适:

在这里插入图片描述


2. 针对上面的问题,JUnit5也给出了方案:通过注解的方式,指定一个从ArgumentsAccessor到Person的转换器,示例如下,可见测试方法的入参有个注解@AggregateWith,其值PersonAggregator.class就是从ArgumentsAccessor到Person的转换器,而入参已经从前面的ArgumentsAccessor变成了Person:

@Order(19) @DisplayName("CsvSource的多个字段,通过指定聚合类转为Person实例") @ParameterizedTest @CsvSource({ "Jane2, Doe2, SMALL", "John2, Doe2, UNKNOWN" }) void customAggregatorTest(@AggregateWith(PersonAggregator.class) Person person) { log.info("customAggregatorTest [{}]", person); }

PersonAggregator是转换器类,需要实现ArgumentsAggregator接口,具体的实现代码很简单,也就是从ArgumentsAccessor示例获取字段创建Person对象的操作:

package com.bolingcavalry.parameterized.service.impl; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; import org.junit.jupiter.params.aggregator.ArgumentsAggregationException; import org.junit.jupiter.params.aggregator.ArgumentsAggregator; public class PersonAggregator implements ArgumentsAggregator { @Override public Object aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) throws ArgumentsAggregationException { Person person = new Person(); person.setFirstName(arguments.getString(0)); person.setLastName(arguments.getString(1)); person.setType(arguments.get(2, Types.class)); return person; } }

上述测试方法的执行结果如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppfxg.html