From dc141eab81ed43f9fa5770ce3a4260b7e88ceedc Mon Sep 17 00:00:00 2001 From: Matthias Merdes Date: Thu, 1 Sep 2016 14:19:05 +0200 Subject: [PATCH] Compose support of method and field support The ExternalResourceSupport is now composed of the two separately implemented support classes for method and field support, respectively. Includes a test to verify the relative order of both cases. #433 --- .../rulesupport/ExternalResourceSupport.java | 72 ++------------ ...pportForMixedMethodAndFieldRulesTests.java | 93 +++++++++++++++++++ 2 files changed, 99 insertions(+), 66 deletions(-) create mode 100644 junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupport.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupport.java index 845b87f1da6e..3f013f68973e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupport.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupport.java @@ -10,85 +10,25 @@ package org.junit.jupiter.engine.vintage.rulesupport; -import static org.junit.platform.commons.util.ReflectionUtils.MethodSortOrder.HierarchyDown; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; -import java.util.stream.Stream; - -import org.junit.Rule; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.TestExtensionContext; -import org.junit.platform.commons.util.AnnotationUtils; -import org.junit.rules.ExternalResource; public class ExternalResourceSupport implements BeforeEachCallback, AfterEachCallback { - private final Class annotationType = Rule.class; - private final Class ruleType = ExternalResource.class; + private AbstractExternalResourceSupport fieldSupport = new ExternalResourceFieldSupport(); + private AbstractExternalResourceSupport methodSupport = new ExternalResourceMethodSupport(); @Override public void beforeEach(TestExtensionContext context) throws Exception { - this.invokeAppropriateMethodOnRuleAnnotatedFields(context, GenericBeforeAndAfterAdvice::before); - this.invokeAppropriateMethodOnRuleAnnotatedMethods(context, GenericBeforeAndAfterAdvice::before); + this.fieldSupport.beforeEach(context); + this.methodSupport.beforeEach(context); } @Override public void afterEach(TestExtensionContext context) throws Exception { - this.invokeAppropriateMethodOnRuleAnnotatedFields(context, GenericBeforeAndAfterAdvice::after); - this.invokeAppropriateMethodOnRuleAnnotatedMethods(context, GenericBeforeAndAfterAdvice::after); - } - - private void invokeAppropriateMethodOnRuleAnnotatedFields(TestExtensionContext context, - Consumer methodCaller) { - // @formatter:off - Stream ruleAdapters = this.findRuleAnnotatedFields(context) - .map(field -> new RuleAnnotatedField(context, field)) - .map(annotatedField -> new ExternalResourceAdapter(annotatedField.getTestRuleInstance())); - // @formatter:on - - ruleAdapters.forEach(methodCaller::accept); - } - - private void invokeAppropriateMethodOnRuleAnnotatedMethods(TestExtensionContext context, - Consumer methodCaller) { - // @formatter:off - Stream ruleAdapters = this.findRuleAnnotatedMethods(context) - .map(method -> new RuleAnnotatedMethod(context, method)) - .map(annotatedMethod -> new ExternalResourceAdapter(annotatedMethod.getTestRuleInstance())); - // @formatter:on - - ruleAdapters.forEach(methodCaller::accept); - } - - private Stream findRuleAnnotatedFields(TestExtensionContext context) { - Object testInstance = context.getTestInstance(); - return findAnnotatedFields(testInstance, this.ruleType, this.annotationType); - } - - private Stream findRuleAnnotatedMethods(TestExtensionContext context) { - Object testInstance = context.getTestInstance(); - List annotatedMethods = AnnotationUtils.findAnnotatedMethods(testInstance.getClass(), - this.annotationType, HierarchyDown); - - return annotatedMethods.stream(); - } - - // TODO: decide whether this should be promoted to AnnotationUtils - private static Stream findAnnotatedFields(Object instance, Class fieldType, - Class annotationType) { - Field[] declaredFields = instance.getClass().getDeclaredFields(); - - // @formatter:off - return Arrays.stream(declaredFields) - .filter(field -> fieldType.isAssignableFrom(field.getType())) - .filter(field -> field.isAnnotationPresent(annotationType)); - // @formatter:on + this.fieldSupport.afterEach(context); + this.methodSupport.afterEach(context); } } diff --git a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java new file mode 100644 index 000000000000..f28958b6cbfb --- /dev/null +++ b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/vintage/rulesupport/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java @@ -0,0 +1,93 @@ +/* + * Copyright 2015-2016 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution and is available at + * + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.junit.jupiter.engine.vintage.rulesupport; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Rule; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.rules.ExternalResource; + +@ExtendWith(ExternalResourceSupport.class) +public class ExternalResourceSupportForMixedMethodAndFieldRulesTests { + + private static boolean beforeOfRule1WasExecuted = false; + private static boolean beforeOfRule2WasExecuted = false; + + private static boolean afterOfRule1WasExecuted = false; + private static boolean afterOfRule2WasExecuted = false; + + private List executions = new ArrayList(); + + @Rule + public ExternalResource resource1 = new ExternalResource() { + @Override + protected void before() throws Throwable { + beforeOfRule1WasExecuted = true; + executions.add("field"); + } + + @Override + protected void after() { + afterOfRule1WasExecuted = true; + } + }; + + private ExternalResource resource2 = new ExternalResource() { + @Override + protected void before() throws Throwable { + beforeOfRule2WasExecuted = true; + executions.add("method"); + } + + @Override + protected void after() { + afterOfRule2WasExecuted = true; + } + }; + + @Rule + public ExternalResource getResource2() { + return resource2; + } + + @Test + void beforeMethodsOfBothRulesWereExecuted() { + assert beforeOfRule1WasExecuted; + assert beforeOfRule2WasExecuted; + } + + @Test + void fieldRuleWasExecutedBeforeMethodRule() { + assertEquals(Arrays.asList("field", "method"), this.executions); + } + + @AfterAll + static void afterMethodsOfBothRulesWereExecuted() { + if (!afterOfRule1WasExecuted) + fail(); + if (!afterOfRule2WasExecuted) + fail(); + } + + static void fail() { + //hack: use this blacklisted exception to fail the build, all others would be swallowed... + throw new OutOfMemoryError("a postcondition was violated"); + } + +}