junit5parameterized-tests

JUnit5 - how to pass input collection to ParameterizedTest


I'm trying to translate a ParameterizedTest from JUnit4 to JUnit5 (sadly I'm not particularly skilled in testing).

In JUnit4 I have the following class:

@RunWith(Parameterized.class)
public class AssertionTestCase {
   private final TestInput testInput;

   public AssertionTestCase(TestInput testInput) {
       this.testInput = testInput;
   }

   @Parameterized.Parameters
   public static Collection<Object[]> data() {
       return AssertionTestCaseDataProvider.createDataCase();
   }

   @Test(timeout = 15 * 60 * 1000L)
   public void testDailyAssertion() {
       LOG.info("Testing input {}/{}", testInput.getTestCase(), testInput.getTestName());

       //assert stuffs
   }
 }

in the AssertionTestCaseDataProvider class I have a simple method generating a collection of Object[]:

class AssertionTestCaseDataProvider {

   static Collection<Object[]> createDataCase() {
       final List<TestInput> testInputs = new ArrayList<>();

       //create and populate testInputs

       return testInputs.stream()
               .map(testInput -> new Object[]{testInput})
               .collect(Collectors.toList());
   }
}

I've been trying to translate it using JUnit5 and obtained this:

class AssertionTestCase {

   private final TestInput testInput;

   public AssertionTestCase(TestInput testInput) {
       this.testInput = testInput;
   }

   public static Collection<Object[]> data() {
       return AssertionTestCaseDataProvider.createDataCase();
   }

   @ParameterizedTest
   @MethodSource("data")
   void testDailyAssertion() {
       LOG.info("Testing input {}/{}", testInput.getTestCase(), testInput.getTestName());

       // assert stuffs
   } 

}

I did not apply any change to the AssertionTestCaseDataProvider class. Nevertheless, I'm getting the following error:

No ParameterResolver registered for parameter [com.xxx.xx.xxx.xxx.testinput.TestInput arg0] in constructor [public `com.xxx.xxx.xxx.xxx.xxx.AssertionTestCase(com.xxx.xxx.xxx.xxx.testinput.TestInput)]. org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [com.xxx.xx.xxx.xxx.testinput.TestInput arg0] in constructor [public com.xxx.xxx.xxx.xxx.xxx.AssertionTestCase(com.xxx.xxx.xxx.xxx.testinput.TestInput)].`

I understand I'm probably not applying correctly JUnit5 when initializing the input collection for the test. Am I missing some annotations?

I've also tried to use @ArgumentSource instead of @MethodSource and implementing Argument for AssertionTestCaseDataProvider, with the same failing results.


Solution

  • It works in a bit another way in Junit5. Test Method should have parameters, and provider method should return a Stream.

    static Stream<Arguments> data(){
        return Stream.of(
           Arguments.of("a", 1),
           Arguments.of("d", 2)
        );
    }
    
    @ParameterizedTest
    @MethodSource("data")
    void testDailyAssertion(String a, int b) {
        Assertions.assertAll(
                () -> Assertions.assertEquals("a", a),
                () -> Assertions.assertEquals(1, b)
        );
    }
    

    In your case you can just return a Stream<TestInput>:

    static Stream<TestInput> createDataCase() {
       final List<TestInput> testInputs = new ArrayList<>();
    
       //create and populate testInputs
    
       return testInputs.stream();
    }
    

    and then in your testMethod:

    @ParameterizedTest
    @MethodSource("createDataCase")
    void testDailyAssertion(TestInput testInput) {
        {your assertions}
    }