Reputation: 3824
I am extending JUnit's ParameterResolver
to provide a custom argument in Test methods.
public class MyParameterResolver implements ParameterResolver {
@Override
public boolean supportsParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) throws ParameterResolutionException {
return parameterContext.getParameter().getType() == MyWrapper.class;
}
@Override
public Object resolveParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) throws ParameterResolutionException {
// Do something about getting MyAnnotation
return new MyWrapper();
}
}
and then using it in test methods using ExtendWith
@ExtendWith(MyParameterResolver.class)
@Test
@MyAnnotation(val = 20)
@MyAnnotation(val = 30)
void test(MyWrapper wrapper) {
System.out.println(wrapper);
}
It works perfectly however I do not like the idea that all the tests which needs this extension would need to be annotated with @ExtendWith(MyParameterResolver.class)
, is it possible to automatically register the annotation in Junit programmatically whenever a test method contains MyWrapper
parameter or MyAnnotation
annotation?
Upvotes: 4
Views: 3787
Reputation: 46116
§5.2 of the JUnit 5 User Guide shows the three ways one can register extensions:
Declaratively with @ExtendWith
(§5.2.1).
Developers can register one or more extensions declaratively by annotating a test interface, test class, test method, or custom composed annotation with
@ExtendWith(…)
and supplying class references for the extensions to register.
Note: If you annotate the class with @ExtendWith(...)
then all enclosed test methods will be extended by the specified extension.
Programmatically with @RegisterExtension
(§5.2.2).
Developers can register extensions programmatically by annotating fields in test classes with
@RegisterExtension
.When an extension is registered declaratively via
@ExtendWith
, it can typically only be configured via annotations. In contrast, when an extension is registered via@RegisterExtension
, it can be configured programmatically — for example, in order to pass arguments to the extension’s constructor, a static factory method, or a builder API.
Automatically via java.util.ServiceLoader
(§5.2.3).
In addition to declarative extension registration and programmatic extension registration support using annotations, JUnit Jupiter also supports global extension registration via Java’s
java.util.ServiceLoader
mechanism, allowing third-party extensions to be auto-detected and automatically registered based on what is available in the classpath.Specifically, a custom extension can be registered by supplying its fully qualified class name in a file named
org.junit.jupiter.api.extension.Extension
within the/META-INF/services
folder in its enclosing JAR file.
Note: Automatic registration must be explicitly enabled.
If you're okay with your extension being registered globally then you can use the automatic registration mechanism. But there does not appear to be a way to only extend test methods if they have a specific parameter type. However, you may be able to create a so-called composed annotation to make things simpler:
@ExtendWith(MyParameterResolver.class)
@Retention(RUNTIME)
@Target(METHOD)
public @interface ComposedAnnotation {
int[] vals(); // int array to (maybe?) replace the multiple @MyAnnotation(val = XXX) annotations
}
Though I don't know if that's compatible with your @MyAnnotation
annotation.
Note that if your implementation of #supportsParameter(ParameterContext,ExtensionContext)
is quick then having the extension registered for methods which don't use it should not be a problem. In other words, it won't significantly slow down your tests or, as far as I know, cause errors.
Upvotes: 4