JUnit5 - @CsvSource - 将源代码转换为 POJO

JUnit5 - @CsvSource - converting source to POJO

我一直在关注一些关于 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 和 getter 创建了 POJO class 并将我的方法更改为:

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 方法?

The official documentation 解释:

To use a custom aggregator, implement the ArgumentsAggregator interface and register it via the @AggregateWith annotation on a compatible parameter in the @ParameterizedTest method. The result of the aggregation will then be provided as an argument for the corresponding parameter when the parameterized test is invoked. Note that an implementation of ArgumentsAggregator must be declared as either a top-level class or as a static nested class.

它会给出:

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

文档还添加了:

If you find yourself repeatedly declaring @AggregateWith(MyTypeAggregator.class) for multiple parameterized test methods across your codebase, you may wish to create a custom composed annotation such as @CsvToMyType that is meta-annotated with @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());
}