Search code examples
javajunit5functional-interface

Is it possible to use Java functional interface implementation (such as the Supplier) as a MethodSource in Junit 5?


Running integration tests I have their arguments stored as jsons inside of diffrent files. Those files store diffrent test cases which are then tested in diffrent methods.

I wonder if it possible to create a generic read file method such as this one:

  static Stream<Arguments> argumentsOf(String fileName) {
    Path argumentsFilePath = Paths.get(ARGUMENTS_FILES_DIRECTORY + fileName);
    //read and return arguments stored in a file 
  }

Together with a functional interface like this one:

     static Supplier<Stream<Arguments>> anExampleArgument =
      () -> argumentsOf("some_test_case_argument.json");

So I can do something like this:

  @ParameterizedTest
  @MethodSource("anExampleArgument.get")
  void test1(String exampleArgument) {
  //...
  }

I couldn't find any information regarding this scenario. The example code seen above results in

org.junit.platform.commons.JUnitException: Could not find factory method [anExampleArgument.get] in class [com.company.ExampleIntegrationTest]

Solution

  • No, at the moment what you describe does not seem to be possible.

    The docs of MethodSource are not very clear on this, but looking at its JavaDoc may provide some insight:

    Factory methods in external classes must be referenced by fully qualified method name — for example, com.example.StringsProviders#blankStrings.

    The code that throws the exception that you're seeing is here:

    private Method getMethod(Class<?> clazz, String methodName) {
        return ReflectionUtils.findMethod(clazz, methodName).orElseThrow(() -> new JUnitException(
        format("Could not find factory method [%s] in class [%s]", methodName, clazz.getName())));
    }
    

    Sadly, their ReflectionUtils class does not seem to include any functionality for evaluating additional calls after a method, so it treats your String as a fully qualified method name.

    Perhaps you'd benefit from creating your own ArgumentsProvider as per this answer?

    As a commenter points out, perhaps Dynamic Tests might also work for your use case.