JeffFaer / junit5-extensions

Personal repository for JUnit 5 extensions
MIT License
40 stars 8 forks source link

[New Feature] Allow injection in Extensions #6

Open ghost opened 5 years ago

ghost commented 5 years ago

As I understand currently this extension allows injection only inside test classes. It would be good to have ability to inject fields inside junit5 custom Extension classes

JeffFaer commented 5 years ago

What's your use case? I think this is already supported if you use @RegisterExtension:

@IncludeModule(MyModule.class)
class MyTest {
  @RegisterExtension @Inject MyExtension myExtension;
}

Will add a test shortly to confirm

ghost commented 5 years ago

Tried your suggestion and it seems it doesn't work. Does it work for you?

My usecase: I need to be able to inject config objects etc. into my custom extensions. Sinse there're several ways to add extension to test class would you like to consider providing guice injector for extensions directly? Perhaps it can be done via base class like InjectableExtension. What do you think about it?

@IncludeModule(MyModule.class)
public MyExtension extends InjectableExtension implements BeforeAllCallback {

    @Inject private InjectedObject obj;

}
JeffFaer commented 5 years ago

This did work for me. See https://github.com/JeffreyFalgout/junit5-extensions/blob/master/guice-extension/src/test/java/name/falgout/jeffrey/testing/junit/guice/InjectExtensionsTest.java

Adding @IncludeModule directly to an extension should be possible, but I'm not convinced it's a good idea.

  1. It seems a little surprising to special type extensions for this type of support. We could support this on all types, but I definitely wouldn't want @IncludeModule on random injectable classes in my code base
  2. It tightly couples your extension to a single module, which limits its reusability (and goes counter to Guice's philosophy)
ghost commented 5 years ago

Try implementing BeforeAllCallback. beforeAll() method is not executed for me.

JeffFaer commented 5 years ago

Ah, that's tricky.

Instance fields cannot implement BeforeAllCallback: https://junit.org/junit5/docs/current/user-guide/#extensions-registration-programmatic-instance-fields:

Thus, if such an instance extension implements class-level or instance-level extension APIs such as BeforeAllCallback, AfterAllCallback, or TestInstancePostProcessor, those APIs will not be honored

And static @RegisterExtension fields are registered before the GuiceExtension gets a chance to inject anything.

Perhaps we need a method to create an instance with GuiceExtension manually. Then we could do something like

  @RegisterExtension private static final MyExtension myExtension = GuiceExtension.getInstance(MyExtension.class);
ghost commented 5 years ago

Sounds good to me