英文:
Is there a way to access values of a custom annotation in a ExecutionCondition of junit 5 tests?
问题
I have the following annotation to mark test code that should not be executed if a server does not listen on a host and port each specified in a properties file:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(DisableOnServerNotListening.class)
public @interface DisabledOnServerNotListening
{
String propertyNameHost() default "host";
String propertyNamePort() default "port";
}
In a junit 5 ExecutionCondition
, I want to look up the actual configured host/port values from the property file to decide if the test should be run (port is listening) or not (port is not listening). Because there may be more than one host/port configuration in my tests, I need to be flexible regarding property names. So how can I access the values of the annotation? Debugging shows that there is a field called testDescriptor
in ExtensionContext
, but it is not exposed for access.
英文:
I have the following annotation to mark test code that should not be executed if a server does not listen on a host and port each specified in a properties file:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(DisableOnServerNotListening.class)
public @interface DisabledOnServerNotListening
{
String propertyNameHost() default "host";
String propertyNamePort() default "port";
}
In a junit 5 ÈxecutionCondition
I want to look up the actual configured host/port values from the property file to decide if the test should be run (port is listening) or not
(port is not listening). Because there may be more than one host/port configuration in my tests I need to be flexible regarding property names. So how can I access the values of the annotation? Debugging shows that there is a field called testDescriptor
in ExtensionContext
, but it is not exposed for access.
答案1
得分: 1
Looking at existing Jupiter functionality you can see that most existing implementations of ExecutionCondition
work with annotations. Thus, what you want to do is possible.
Let's look at (parts of) the implementation of DisabledCondition
:
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;
class DisabledCondition implements ExecutionCondition {
private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled(
"@Disabled is not present");
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
AnnotatedElement element = context.getElement().orElse(null);
return findAnnotation(element, Disabled.class) //
.map(annotation -> toResult(element, annotation)) //
.orElse(ENABLED);
}
private ConditionEvaluationResult toResult(AnnotatedElement element, Disabled annotation) {
String value = annotation.value();
String reason = StringUtils.isNotBlank(value) ? value : element + " is @Disabled";
return ConditionEvaluationResult.disabled(reason);
}
}
If you replace Disabled
with DisabledOnServerNotListening
you have a head start on the implementation of your own ExecutionCondition
subtype.
The actual checking code for host availability would probably reside within the toResult
method. Similar to:
private ConditionEvaluationResult toResult(AnnotatedElement element, DisabledOnServerNotListening annotation) {
String hostPropName = annotation.propertyNameHost();
String portPropName = annotation.propertyNamePort();
boolean disabled = !checkIfHostIsListening(hostPropName, portPropName);
if (disabled)
return ConditionEvaluationResult.disabled("host not listening");
else
return ConditionEvaluationResult.enabled();
}
英文:
Looking at existing Jupiter functionality you can see that most existing implementations of ExecutionCondition
work with annotations. Thus, what you want to do is possible.
Let's look at (parts of) the implementation of DisabledCondition
:
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;
class DisabledCondition implements ExecutionCondition {
private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult.enabled(
"@Disabled is not present");
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
AnnotatedElement element = context.getElement().orElse(null);
return findAnnotation(element, Disabled.class) //
.map(annotation -> toResult(element, annotation)) //
.orElse(ENABLED);
}
private ConditionEvaluationResult toResult(AnnotatedElement element, Disabled annotation) {
String value = annotation.value();
String reason = StringUtils.isNotBlank(value) ? value : element + " is @Disabled";
return ConditionEvaluationResult.disabled(reason);
}
}
If you replace Disabled
with DisabledOnServerNotListening
you have a head start on the implementation of your own ExecutionCondition
subtype.
The actual checking code for host availability would probably reside within the toResult
method. Similar to:
private ConditionEvaluationResult toResult(AnnotatedElement element, DisabledOnServerNotListening annotation) {
String hostPropName = annotation.propertyNameHost();
String portPropName = annotation.propertyNamePort();
boolean disabled = !checkIfHostIsListening(hostPropName, portPropName);
if (disabled)
return ConditionEvaluationResult.disabled("host not listening");
else
return ConditionEvaluationResult.enabled();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论