JUnit5-@CsvSource-将源转换为POJO

时间:2019-02-25 13:01:13

标签: java junit junit5

我一直在学习一些有关JUnit测试的在线课程,并且遇到了@CsvSource的示例。以下示例效果很好。

@DisplayName("CSV input test")
@ParameterizedTest(name = DISPLAY_NAME_PLACEHOLDER + " - [" + INDEX_PLACEHOLDER + "] " + ARGUMENTS_PLACEHOLDER)
@CsvSource({
        "FL, 1, 1",
        "OH, 2, 2",
        "MI, 3, 3"
})
void csvInputTest(String stateCode, int val1, int val2) {
    System.out.println(stateCode + " - " + val1 + " - " + val2);
}

然后我开始怀疑我是否可以使用一些POJO代替参数的基础。所以我用setter和getters创建了POJO类,并将方法更改为:

void csvInputTest(StateInfo stateInfo) {
    System.out.println(stateInfo.getStateCode() + " - " + stateInfo.getVal1() + " - " + stateInfo.getVal2());
}

但这导致:

org.junit.jupiter.api.extension.ParameterResolutionException: Error converting parameter at index 0: No implicit conversion to convert object of type java.lang.String to type StateInfo

我在@CsvSource中找不到任何字段来指定任何转换器,所以我的问题是-我可以这样做吗?还是我必须坚持使用N-arguments方法?

1 个答案:

答案 0 :(得分:5)

The official documentation对此进行了说明:

  

要使用自定义聚合器,请实现ArgumentsAggregator   界面,并通过@AggregateWith批注在   @ParameterizedTest方法中的兼容参数。的结果   然后,聚合将作为   调用参数化测试时的相应参数。注意   必须将ArgumentsAggregator的实现声明为   顶层类还是静态嵌套类。

它将给出:

public class StateInfoAggregator implements ArgumentsAggregator {
    @Override
    public StateInfo aggregateArguments(ArgumentsAccessor arguments, ParameterContext context) {
        return new StateInfo(arguments.getString(0),
                             arguments.getInteger(1),
                             arguments.getInteger(1));

    }
}

@ParameterizedTest
@CsvSource({
        "FL, 1, 1",
        "OH, 2, 2",
        "MI, 3, 3"
})
void csvInputTest(@AggregateWith(StateInfoAggregator.class) StateInfo stateInfo) {
    System.out.println(stateInfo.getStateCode() + " - " + stateInfo.getVal1() + " - " + stateInfo.getVal2());
}

文档还添加了:

  

如果您发现自己反复声明   @AggregateWith(MyTypeAggregator.class)用于多个参数化测试   您整个代码库中的方法,您可能希望创建一个自定义的   带有@注释的注释,例如@CsvToMyType   @AggregateWith(MyTypeAggregator.class)。

它将给出:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@AggregateWith(StateInfoAggregator.class)
public @interface CsvToStateInfo {
}

@ParameterizedTest
@CsvSource({
        "FL, 1, 1",
        "OH, 2, 2",
        "MI, 3, 3"
})
void csvInputTest(@CsvToStateInfo  StateInfo stateInfo) {
    System.out.println(stateInfo.getStateCode() + " - " + stateInfo.getVal1() + " - " + stateInfo.getVal2());
}