Junit 5 parameterized tests

My favourite feature of Junit 5 is its improvement to parameterized tests. Previously, each parameterized test must be written in its own class. In the test class, you define a method for the test and another method for its inputs and outputs. Junit 5 provides a much simpler way to define parameterized tests. You can now annotate individual test methods as parameterized, with parameters supplied via annotations.

For example, the following test verifies the method under test throws an InvalidRequestException with the specified list of ISO dates.

@ParameterizedTest
@ValueSource(strings= {"1752-12-31T21:45:00", "10000-01-01T21:45:00"})
public void invalidDate(String testdate) {
    testRequest.setDate(testdate);
    assertThrows(InvalidRequestException.class, 
        () -> testService.testMethod(ORDER_ID, testRequest));
}

With the enum value source and exclude mode, it’s now very easy to test status validation to make sure all statuses except a few are allowed. For example, the code below checks an order can be cancelled only in the PREPROCESS status.

@ParameterizedTest
@EnumSource(value = OrderStatus.class, mode = Mode.EXCLUDE, 
            names = {"PREPROCESS"})
public void testOrderStatusCancellation(OrderStatus status) throws Exception {
    testOrder.setStatus(status);
    assertThrows(InvalidRequestException.class
        () -> testService.cancel(testOrder));
}

If your parameterized test inputs and outputs are more complicated, and cannot be easily supplied inside annotation, you can use the @MethodSource annotation. This allows you to define your test method inputs and outputs with another method, similar to how things were before Junit 5.

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

@ParameterizedTest
@MethodSource("inputOutputProvider")
public void testCodeParsing(String input, Set<Integer> expected) {
    assertEquals(expected, codeReader.getRejectionCodes(comment));
}

private static Stream<Arguments> inputOutputProvider() {
    return Stream.of(
        Arguments.arguments("0010,0015,0041", newHashSet(10,15,41)),
        Arguments.arguments("C22", newHashSet(22)),
        Arguments.arguments("10", newHashSet(10)));
}