javajunit5-extension-model

How to create a test for a custom ParameterResolver implementation?


I've created a ParameterResolver implementation in order to inject a parameter into my test methods. I have a scenario where the instantiation of the parameter object could fail without some proper parameters defined by the correspondent annotation and an exception is thrown.

  @TestScenario(homeDirName = "")
  @Test
  void ensureFailingWithoutProperHomeDirectory(LauncherRuntime launcher) {

    assertThrows(MissingPropertiesException.class,
                 () -> launcher.run());
  }

But this test is failing even before starting to run, with a ParameterResolutionException.

I would like to know how can I test it.


Solution

  • Since you want to test your ParameterResolver implementation and not the JUnit engine the entry point of your Unit test should be the provideArguments method of your implementation. JUnit catches every exception that is thrown by this method and adds it as cause for a new ParameterResolutionException. There are two possible approaches:

    A) If your implementation should call multiple methods of ExtensionContext then mock these methods together with your annotation. And call the provideArguments of your implementation.

    B) If your implementation should use the ExtensionContext only to get the annotation and does nothing more with it that is worth for testing, then move main functionality into an own method (e.g. accept(MyAnnotation)) and test this method. See for example here how the JUnit developers to this for the CVSSource annotation.

    Here's an example test case for my ResourceFilesArgumentsProvider / ResourceFilesSource annotation:

    import static org.junit.jupiter.api.Assertions.assertThrows;
    import static org.mockito.Mockito.mock;
    import static org.mockito.Mockito.when;
    
    class ResourceFilesArgumentsProviderTest {
    
      @Test
      public void nonExistingDirectory() throws Exception {
    
        ResourceFilesSource annotation = resourceFiles("/non-existing-dir");
    
        AnnotatedElement annotatedElement = mock(AnnotatedElement.class);
    
        when(annotatedElement.getAnnotation(ResourceFilesSource.class))
          .thenReturn(annotation);
    
        ExtensionContext context = mock(ExtensionContext.class);
        when(context.getElement()).thenReturn(Optional.of(annotatedElement));
        when(context.getTestClass()).thenReturn(Optional.of(getClass()));
    
        assertThrows(NoSuchFileException.class, () -> provideArguments(context));
      }
    
      private Stream<Object[]> provideArguments(ExtensionContext context) throws Exception {
        ResourceFilesArgumentsProvider provider = new ResourceFilesArgumentsProvider();
        return provider.provideArguments(context).map(Arguments::get);
      }
    
      private ResourceFilesSource resourceFiles(String directory) {
    
        /* mock the annotation with Mockito, or alternatively create
         * an anonymous class with new ResourceFileSource() { ... }
         */
        ResourceFilesSource annotation = mock(ResourceFilesSource.class);
        when(annotation.directory()).thenReturn(directory);
        return annotation;
      }
    
    }