Reputation: 2949
How can I write a parameterized test with two arguments in JUnit 5 jupiter? The following does not work (compile error):
@ParameterizedTest
@ValueSource(strings = { "a", "b", "foo" })
@ValueSource(ints = { 1, 2, 3 })
public void test(String arg1, int arg2) {
// ...
}
Upvotes: 116
Views: 94721
Reputation: 3203
Consider a simple function to test:
public static boolean isDivisibleBy(int dividend, int divisor){
return dividend % divisor == 0;
}
When generating JUnit5 Parameterized Test case:
Use @DisplayName
annotation with a message.
Use @ParameterizedTest
with name
argument.
Use @ParameterizedTest(name = "
with {0}..{N}
")
to point to @CsvSource
's values.
Use @CsvSource({"key1,value1", "key2,value2", "key3,value3", .. })
without worry of conversion.
This mechanism is based on implicit converters that can interpret a String
into another type, such as int
. This particular example may not seem that impressive, but it works with a lot of very useful common types, such as File
, Path
, BigDecimal
, Date
, Time
, enum
and URL
.
Don't use @Test
along with @ParameterizedTest
.
Example:
@DisplayName("Divide Test Cases 😎")
@ParameterizedTest(name = "{0} is multiple of {1}")
@CsvSource({"2,2", "4,2", "7,3"})
void shouldReturnTrueForVariousDivisiblePairs(int givenDividend, int givenDivisor) {
assertTrue(isDivisibleBy(givenDividend, givenDivisor));
}
Pretty Output Log:
Upvotes: 12
Reputation: 24482
Here is a solution using Kotlin language:
class MyTests {
@ParameterizedTest
@MethodSource("generateArgs")
fun myTest(myArg: Pair<String, Int>) {
val (name, age) = myArg // Destructuring; could instead use myArg.first and myArg.second
println("$name $age")
}
companion object {
@JvmStatic
fun generateArgs() = listOf (
"A" to 1,
"B" to 2,
"C" to 3
)
}
}
Upvotes: 2
Reputation: 9131
Here are two possibilities to achieve these multi argument test method calls.
The first (testParameters) uses a CsvSource to which you provide a comma separated list (the delimiter is configurable) and the type casting is done automatically to your test method parameters.
The second (testParametersFromMethod) uses a method (provideParameters) to provide the needed data.
@ParameterizedTest
@CsvSource({"a,1", "b,2", "foo,3"})
public void testParameters(String name, int value) {
System.out.println("csv data " + name + " value " + value);
}
@ParameterizedTest
@MethodSource("provideParameters")
public void testParametersFromMethod(String name, int value) {
System.out.println("method data " + name + " value " + value);
}
private static Stream<Arguments> provideParameters() {
return Stream.of(
Arguments.of("a", 1),
Arguments.of("b", 2),
Arguments.of("foo", 3)
);
}
The output of these test methods are:
Running ParameterTest
csv data a value 1
csv data b value 2
csv data foo value 3
method data a value 1
method data b value 2
method data foo value 3
Upvotes: 190