Search code examples
dependency-injectionjunit5

Can I specify an instance of a test class when using a JUnit5 launcher


I would like to programmatically launch JUnit5 tests not on a class but on a specific instance of the class so I can perform dependency injection through the class's constructor.

I can launch execution on a class with:

launcher.execute(request().selectors(selectClass(MyTest.class)).build());

Is there a way to instead launch it on, for example, new MyTest(someParameter)?


Solution

  • Use a Jupiter extension for this purpose. Either TestInstanceFactory or TestInstancePostProcessor look like good candidates:

    class CreateMyTestExtension implements TestInstanceFactory {
    
        @Override
        public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) throws TestInstantiationException {
            String param = "a string"; // Get it from wherever
            return new MyTest(param);
        }
    }
    
    
    @ExtendWith(CreateMyTestExtension.class)
    class MyTest {
    
        private final String param;
    
        MyTest(String param) {
            this.param = param;
        }
    
        @Test
        void aTest() {
            System.out.println("param = " + param);
        }
    }
    

    You can then run your test through the IDE or Gradle or Maven or use the standard code for launcher as suggested in the question:

    launcher.execute(request().selectors(selectClass(MyTest.class)).build());
    

    The open question is: Where does param come from? Depending on the answer to that you may have to use additional configuration parameters. Those can be set for a discovery request during launching and queried from the extension context: extensionContext.getConfigurationParameter("param1").