1. 程式人生 > >JUnit5中@ParameterizedTest 處理 @CvsSource中的空值

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