Skip to content

Commit

Permalink
Return Optional from ExtensionContext.getElement()
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrannen committed Jun 25, 2016
1 parent 25e0938 commit d6eccb9
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 29 deletions.
7 changes: 3 additions & 4 deletions documentation/src/docs/asciidoc/release-notes-5.0.0-M1.adoc
Expand Up @@ -8,13 +8,12 @@


===== JUnit Platform ===== JUnit Platform


- *TODO* - `org.junit.platform.console.ConsoleRunner` has been renamed to `ConsoleLauncher`
- `ConsoleRunner` has been renamed to `ConsoleLauncher`


===== JUnit Jupiter ===== JUnit Jupiter


- *TODO* - `ExtensionContext.getElement()` now returns `Optional<AnnotatedElement>`.


===== JUnit Vintage ===== JUnit Vintage


- *TODO* - ???
Expand Up @@ -80,6 +80,25 @@ public interface ExtensionContext {
*/ */
Set<String> getTags(); Set<String> getTags();


/**
* Get the {@link AnnotatedElement} corresponding to the current extension
* context, if available.
*
* <p>For example, if the current extension context encapsulates a test
* class or test method, the annotated element will be the corresponding
* {@link Class} or {@link Method} reference.
*
* <p>Favor this method over more specific methods whenever the
* {@code AnnotatedElement} API suits the task at hand &mdash; for example,
* when looking up annotations regardless of concrete element type.
*
* @return an {@code Optional} containing the {@code AnnotatedElement};
* never {@code null} but potentially empty
* @see #getTestClass()
* @see #getTestMethod()
*/
Optional<AnnotatedElement> getElement();

/** /**
* Get the {@link Class} associated with the current test or container, * Get the {@link Class} associated with the current test or container,
* if available. * if available.
Expand All @@ -97,25 +116,6 @@ public interface ExtensionContext {
*/ */
Optional<Method> getTestMethod(); Optional<Method> getTestMethod();


/**
* Get the {@link AnnotatedElement} corresponding to the current extension
* context.
*
* <p>For example, if the current extension context encapsulates a test
* class or test method, the annotated element will be the corresponding
* {@link #getTestClass() Class} or {@link #getTestMethod() Method}
* reference.
*
* <p>Favor this method over more specific methods whenever the
* {@link AnnotatedElement} API suits the task at hand &mdash; for example,
* when looking up annotations regardless of concrete element type.
*
* @return the {@code AnnotatedElement}; never {@code null}
* @see #getTestClass()
* @see #getTestMethod()
*/
AnnotatedElement getElement();

/** /**
* Publish a map of key-value pairs to be consumed by an * Publish a map of key-value pairs to be consumed by an
* {@code org.junit.platform.engine.EngineExecutionListener}. * {@code org.junit.platform.engine.EngineExecutionListener}.
Expand Down
Expand Up @@ -44,8 +44,8 @@ public String getDisplayName() {
} }


@Override @Override
public AnnotatedElement getElement() { public Optional<AnnotatedElement> getElement() {
return getTestClass().get(); return Optional.of(getTestDescriptor().getTestClass());
} }


@Override @Override
Expand Down
Expand Up @@ -47,8 +47,8 @@ public String getDisplayName() {
} }


@Override @Override
public AnnotatedElement getElement() { public Optional<AnnotatedElement> getElement() {
return getTestMethod().get(); return Optional.of(getTestDescriptor().getTestMethod());
} }


@Override @Override
Expand Down
Expand Up @@ -53,7 +53,7 @@ public ConditionEvaluationResult evaluate(TestExtensionContext context) {
return evaluate(context.getElement()); return evaluate(context.getElement());
} }


private ConditionEvaluationResult evaluate(AnnotatedElement element) { private ConditionEvaluationResult evaluate(Optional<AnnotatedElement> element) {
Optional<Disabled> disabled = findAnnotation(element, Disabled.class); Optional<Disabled> disabled = findAnnotation(element, Disabled.class);
if (disabled.isPresent()) { if (disabled.isPresent()) {
String reason = disabled.map(Disabled::value).filter(StringUtils::isNotBlank).orElseGet( String reason = disabled.map(Disabled::value).filter(StringUtils::isNotBlank).orElseGet(
Expand Down
Expand Up @@ -68,6 +68,22 @@ public static boolean isAnnotated(AnnotatedElement element, Class<? extends Anno
return findAnnotation(element, annotationType).isPresent(); return findAnnotation(element, annotationType).isPresent();
} }


/**
* Find the first annotation of {@code annotationType} that is either <em>present</em> or <em>meta-present</em> on
* the supplied optional {@code element}.
*
* @see #findAnnotation(AnnotatedElement, Class)
*/
public static <A extends Annotation> Optional<A> findAnnotation(Optional<? extends AnnotatedElement> element,
Class<A> annotationType) {

if (element == null || !element.isPresent()) {
return Optional.empty();
}

return findAnnotation(element.get(), annotationType, new HashSet<Annotation>());
}

/** /**
* Find the first annotation of {@code annotationType} that is either <em>present</em> or <em>meta-present</em> on * Find the first annotation of {@code annotationType} that is either <em>present</em> or <em>meta-present</em> on
* the supplied {@code element}. * the supplied {@code element}.
Expand Down
Expand Up @@ -31,6 +31,7 @@
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
Expand All @@ -44,9 +45,19 @@
*/ */
class AnnotationUtilsTests { class AnnotationUtilsTests {


@Test
void findAnnotationForNullOptional() {
assertThat(findAnnotation((Optional<AnnotatedElement>) null, Annotation1.class)).isEmpty();
}

@Test
void findAnnotationForEmptyOptional() {
assertThat(findAnnotation(Optional.empty(), Annotation1.class)).isEmpty();
}

@Test @Test
void findAnnotationForNullAnnotatedElement() { void findAnnotationForNullAnnotatedElement() {
assertThat(findAnnotation(null, Annotation1.class)).isEmpty(); assertThat(findAnnotation((AnnotatedElement) null, Annotation1.class)).isEmpty();
} }


@Test @Test
Expand All @@ -56,6 +67,14 @@ void findAnnotationOnClassWithoutAnnotation() {
assertFalse(optionalAnnotation.isPresent()); assertFalse(optionalAnnotation.isPresent());
} }


@Test
void findAnnotationIndirectlyPresentOnOptionalClass() {
Optional<InheritedAnnotation> optionalAnnotation = findAnnotation(
Optional.of(SubInheritedAnnotationClass.class), InheritedAnnotation.class);
assertNotNull(optionalAnnotation);
assertTrue(optionalAnnotation.isPresent());
}

@Test @Test
void findAnnotationIndirectlyPresentOnClass() { void findAnnotationIndirectlyPresentOnClass() {
Optional<InheritedAnnotation> optionalAnnotation = findAnnotation(SubInheritedAnnotationClass.class, Optional<InheritedAnnotation> optionalAnnotation = findAnnotation(SubInheritedAnnotationClass.class,
Expand Down Expand Up @@ -105,6 +124,14 @@ void findAnnotationMetaPresentOnMethod() throws Exception {
assertTrue(optionalAnnotation.isPresent()); assertTrue(optionalAnnotation.isPresent());
} }


@Test
void findAnnotationMetaPresentOnOptionalMethod() throws Exception {
Optional<Annotation1> optionalAnnotation = findAnnotation(
Optional.of(ComposedAnnotationClass.class.getDeclaredMethod("method")), Annotation1.class);
assertNotNull(optionalAnnotation);
assertTrue(optionalAnnotation.isPresent());
}

@Test @Test
void isAnnotatedForClassWithoutAnnotation() { void isAnnotatedForClassWithoutAnnotation() {
assertFalse(isAnnotated(Annotation1Class.class, Annotation2.class)); assertFalse(isAnnotated(Annotation1Class.class, Annotation2.class));
Expand Down

0 comments on commit d6eccb9

Please sign in to comment.