翻译:叩丁狼教育吴嘉俊
在JUnit4中测试方法参数是非常麻烦的事情(注:针对同一个方法,测试多组不同的参数值)。JUnit5中引入了大量的新的特性,让使用同一个测试方法,测试不同的参数变得非常容易。但是,这里面有一个问题值得讨论,就是测试空值的问题。
在这篇文章中,我们会讨论在JUnit5中,如何通过@CvsSource和@ValueSource为@ParameterizedTest测试传入一个空值。
我们通过一个例子来引入这个问题。
假设,我们已经创建了一个类,名字叫做DateRange,这个类包含两个日期参数,用来表示一段时间。你可以通过调用DateRange的构造方法,传入至少一个日期对象,来创建一个DateRange对象。我们在构造方法中也会检查,开始时间必须在结束时间之前。
使用Junit5提供的@ParametrizedTest我们可以非常方便的进行DateRange构造器的测试:
@ParameterizedTest
@CsvSource({
"2017-06-01, 2018-10-15",
"null, 2018-10-15",
"2017-06-01, null"
})
void shouldCreateValidDateRange(LocalDate startDate, LocalDate endDate) {
new DateRange(startDate, endDate);
}
@ParameterizedTest
@CsvSource({
"2018-10-15, 2017-06-01",
"null, null"
})
void shouldNotCreateInvalidDateRange(LocalDate startDate, LocalDate endDate) {
assertThrows(IllegalArgumentException.class, () -> new DateRange(startDate, endDate));
}
当你运行这个测试,可能会得到类似如下的异常提示:
org.junit.jupiter.api.extension.ParameterResolutionException: Error converting parameter at index 0: Failed to convert String “null” to type java.time.LocalDate
这是因为,虽然JUnit5中提供了多种内置的类型转换器用于将@CvsSource或者@ValueSource中的字符串转换成不同类型,但是null值是不能转化成空值的,仍然只能作为一个null字符串存在。
那我们就不能在Junit5中使用空值测试了?
幸运的是,Junit5提供了非常灵活和方便的扩展方式。
默认情况下,框架使用DefaultArgumentConverter类将String转化为其他类型。我们的目标就是把@CvsSource中的null字符串变成null值,其他的字符串仍然使用默认的转化器执行转化。
为了达到这个目标,我们需要继承SimpleArgumentConverter并实现抽象方法convert()方法,在该方法中,我们检查null字符串,如果发现是null字符串,返回null值,其他的继续交给默认转化器:
import org.junit.jupiter.params.converter.DefaultArgumentConverter;
public final class NullableConverter extends SimpleArgumentConverter {
@Override
protected Object convert(Object source, Class> targetType) throws ArgumentConversionException {
if ("null".equals(source)) {
return null;
}
return DefaultArgumentConverter.INSTANCE.convert(source, targetType);
}
}
注意,其中的DefaultArgumentConverter.INSTANCE.convert()方法是从JUnit5.2版本开始的。
一旦我们的转换器做好,我们就可以在测试中使用@ConvertWith注解来标记我们的测试参数:
@ParameterizedTest
@CsvSource({
"2017-06-01, 2018-10-15",
"null, 2018-10-15",
"2017-06-01, null"
})
void shouldCreateValidDateRange(@ConvertWith(NullableConverter.class) LocalDate startDate,
@ConvertWith(NullableConverter.class) LocalDate endDate) {
new DateRange(startDate, endDate);
}
到这里,你应该已经知道如何在Junit5的参数测试中接受null值了。举一反三,类似的特殊的转换,也可以轻易实现。
原文:https://www.javacodegeeks.com/2018/10/parameterizedtest-null-values-cvssource.html