JUnit5中@ParameterizedTest 處理 @CvsSource中的空值
翻譯:叩丁狼教育吳嘉俊
在JUnit4中測試方法引數是非常麻煩的事情(注:針對同一個方法,測試多組不同的引數值)。JUnit5中引入了大量的新的特性,讓使用同一個測試方法,測試不同的引數變得非常容易。但是,這裡面有一個問題值得討論,就是測試空值的問題。
在這篇文章中,我們會討論在JUnit5中,如何通過@CvsSource和@ValueSource為@ParameterizedTest測試傳入一個空值。
在@CvsSource中的空值
我們通過一個例子來引入這個問題。
假設,我們已經建立了一個類,名字叫做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中使用空值測試了?
自定義Null轉換器
幸運的是,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版本開始的。
使用Null轉換器
一旦我們的轉換器做好,我們就可以在測試中使用@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