Hakanai
Hakanai

Reputation: 12678

Can JUnit 5 actually inject extension instances?

The documentation for @RegisterExtension mentions something about injection of the instance:

the extension will be registered after the test class has been instantiated and after all TestInstancePostProcessors have been given a chance to post-process the test instance (potentially injecting the instance of the extension to be used into the annotated field).

Are there any post-processors in JUnit which can do this for extensions automatically, or is this just talking about things people might build in the future?

In our case, I found that many of our extensions turn out to be like this:

    @RegisterExtension
    public final TempFolderExtension temp = new TempFolderExtension();

    @RegisterExtension
    public final SomeFactoryExtension factory = new SomeFactoryExtension(temp);

A container like PicoContainer could automatically figure out how to construct the instances.

It would be really nifty if we could just write,

    @RegisterExtension
    public TempFolderExtension temp;

    @RegisterExtension
    public SomeFactoryExtension factory;

And either an annotation processor or a runtime injector could fill in the rest.

Dependencies between this sort of extension also has implications for the order they should run in.

Upvotes: 3

Views: 1987

Answers (2)

JojOatXGME
JojOatXGME

Reputation: 3296

I don't know if such an extension exists. I think it is more common in the JUnit 5 ecosystem to register extensions with @ExtendWith. The extension can then inject interfaces into the test.

@ExtendWith(TempFolderExtension.class)
static final class SomeTest {

    public TempFolderInterface temp;

    @Test
    void test() {
        ...
    }
}

However, if you want to have an extension as proposed in the question, it would be simple to implement one. Here is ExtensionInjector, a working implementation for such extension.

final class ExtensionInjector implements TestInstancePostProcessor {
    @Override
    public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception {
        List<Field> fields = ReflectionSupport.findFields(
                testInstance.getClass(),
                field -> AnnotationSupport.isAnnotated(field, RegisterExtension.class),
                HierarchyTraversalMode.BOTTOM_UP);
        for (Field field : fields) {
            field.trySetAccessible();
            if (field.get(testInstance) == null) {
                field.set(testInstance, ReflectionSupport.newInstance(field.getType()));
            }
        }
    }
}

You can add this extension to your project as documented in the JUnit 5 User Guide.

Upvotes: 1

Zafiro Geta
Zafiro Geta

Reputation: 49

Short answer: No, it is not possible, when using @RegisterExtension you have to construct your extension instance manually.

Read https://junit.org/junit5/docs/current/user-guide/#extensions 5.2.2

Upvotes: 0

Related Questions