文字列配列(String[]
)をパラメーターとして取るJUnit 5パラメータ化テストを記述したいと思います。
@ParameterizedTest
@MethodSource("stringArrayProvider")
void parseFirstAndSecondInt(String[] args) {
Arguments arguments = new Arguments(args);
assertEquals(1, arguments.getFirst());
assertEquals(2, arguments.getSecond());
}
文字列配列のコレクション/ストリーム/イテレータを提供する方法がわかりません。私は@MethodSource
アノテーションを使用したアプローチに失敗しました
static Stream<String[]> stringArrayProvider() {
return Stream.of(
new String[]{"1", "2"},
new String[]{"1", "2", "3"});
}
しかし、私はこの例外を受けています:
org.junit.jupiter.params.converter.ArgumentConversionException:
No implicit conversion to convert object of type Java.lang.String to type [Ljava.lang.String;
そのような種類のパラメーター化されたテストを行うための良い設計/ソリューションは何でしょうか?
_org.junit.jupiter.params.provider.Arguments
_のArguments.of()
ファクトリを使用して、引数をラップします。
_static Stream<Arguments> stringArrayProvider() {
return Stream.of(
Arguments.of((Object) new String[]{"1", "2"}),
Arguments.of((Object) new String[]{"1", "2", "3"})
);
}
_
詳細については、 http://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests を参照してください
私が使用する最初の一般的な経験則:
同じ生成されたテストケースを複数のテストクラスで使用できる場合は、@ArgumentSource
(ソリューション)を使用します
同じ生成されたテストケースを(同じクラスの)複数のテストメソッドで使用できる場合は、@MethodSource
( Sormuras solution)を使用します。
それ以外の場合は、テストケースのソースを、それらを使用するメソッドにできるだけローカルに保つようにします。
この最後の状況では、2つの単純な可能性を想定しています。
あなたは、固定数の文字列に興味があります(したがって、本当に配列は必要ありません)。 @CsvSource
を使用できます
ここに2つの文字列の例があります(おそらくコンマも含まれています)。
@ParameterizedTest
@CsvSource({ "foo, 1", "bar, 2", "'baz, qux', 3" })
void testWithCsvSource(String first, String second) {
assertNotNull(first);
assertNotEquals(0, second);
}
この場合、さまざまな要素が実際には文字列ではない場合、おそらく自動的に正しい型に解析される可能性があることに注意してください(たとえば、質問では整数が必要なようです)
本当に可変サイズの文字列配列が必要です。この場合、@ValueSource
を使用して、その内容をString []に変換できます。
直接:
@ParameterizedTest
@ValueSource(strings = {"1, 2",
"1, 2, 3"})
void testWithArrayOfStrings(String arg) { // the single csv String parameter
String[] arrayParam = arg.split("\\s*,\\s*"); // is converted to an array of Strings
...
}
または、@ ConvertWithで示される明示的なコンバータークラスを使用します。
@ParameterizedTest
@ValueSource(strings={"1, 2", "1, 2, 3"})
void testWithArrayOfStrings(@ConvertWith(CSVtoArray.class)String... arg)
{
...
}
public static class CSVtoArray extends SimpleArgumentConverter {
@Override
protected Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {
String s = (String) source;
return s.split("\\s*,\\s*");
}
}
Sormurasのソリューション の代替案は、アノテーション@ArgumentsSource
の使用で、非常によく似た方法で機能します。
static class StringArrayProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {
return Stream.of(
(Object) new String[]{"1", "2"},
(Object) new String[]{"1", "2", "3"}).map(Arguments::of);
}
}
それでも、String[]
からObject
へのキャストは奇妙に見え、Niceデザインよりも回避策を感じています。