Search code examples
javajunitjunit5junit-jupiter

Create test instance in Junit 5 with factory method (no dynamic test)


Using JUnit 4, one could take control over test instance lifecycle using runners. For instance, I used to implement method createTest() of BlockJUnit4ClassRunner to have a fine-tuned instance creation (in my case, use Weld to retrieve a CDI-ready instance).

With JUnit 5, extensions are supposed to replace runners and rules. Yet, I cannot find a way to hook into test instance creation the way I could with JUnit 4.

Is there a way to tell JUnit Jupiter how to create my test instance (for example, using Weld container) without using dynamic tests?

Here is what I do now in JUnit 4, and want to be able to do in Jupiter:

public class ContainerRunner extends BlockJUnit4ClassRunner {

    private WeldContainer container;

    ...

    @Override
    public Object createTest() {
        return container.select(this.getTestClass().getJavaClass()).get();
    }
}

And later:

@RunWith(ContainerRunner.class)
@Singleton
public class ContainedTest {

    @Inject
    private Logger logger;  // this works

    @Test
    public void testSomething() {
        ...
    }
}

Thanks for any insights.


Solution

  • By now, it's probably best to use one of the two Weld JUnit 5 Extensions.

    But to answer your question directly, you can (3 years later) write an extension that implements TestInstanceFactory, i.e.:

    class ContainerExtension implements TestInstanceFactory {
        private WeldContainer container;
    
        @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) throws TestInstantiationException {
            return container.select(this.getTestClass().getJavaClass()).get();
        }
    }
    

    Then your test uses @ExtendWith(ContainerExtension.class) instead of @RunWith(ContainerRunner.class).