Skip to content

Commit

Permalink
Reduce code duplication in ClassTestDescriptor
Browse files Browse the repository at this point in the history
This commit also ensures that @beforeeach and @AfterEach methods are not
declared as static, thereby enforcing the contract defined in the
Javadoc for @beforeeach and @AfterEach.

------------------------------------------------------------------------
On behalf of the community, the JUnit Lambda Team thanks
Samuraism, Inc. (http://samuraism.com/) for supporting the
JUnit crowdfunding campaign!
------------------------------------------------------------------------
  • Loading branch information
sbrannen committed Jan 2, 2016
1 parent eb4d640 commit 452687e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 65 deletions.
Expand Up @@ -100,19 +100,12 @@ void fromSuperclass() {


private static class LocalTestCase extends AbstractTestCase { private static class LocalTestCase extends AbstractTestCase {


static boolean staticBeforeInvoked = false;

boolean beforeInvoked = false; boolean beforeInvoked = false;


boolean throwExceptionInAfterMethod = false; boolean throwExceptionInAfterMethod = false;


static int countAfterInvoked = 0; static int countAfterInvoked = 0;


@BeforeEach
static void staticBefore() {
staticBeforeInvoked = true;
}

@BeforeEach @BeforeEach
void before() { void before() {
this.beforeInvoked = true; this.beforeInvoked = true;
Expand All @@ -132,7 +125,6 @@ void after() {
@Test @Test
void methodLevelCallbacks() { void methodLevelCallbacks() {
assertTrue(this.beforeInvoked, "@BeforeEach was not invoked on instance method"); assertTrue(this.beforeInvoked, "@BeforeEach was not invoked on instance method");
assertTrue(staticBeforeInvoked, "@BeforeEach was not invoked on static method");
} }


@Test @Test
Expand Down
Expand Up @@ -13,10 +13,11 @@
import static org.junit.gen5.commons.util.AnnotationUtils.findAnnotatedMethods; import static org.junit.gen5.commons.util.AnnotationUtils.findAnnotatedMethods;
import static org.junit.gen5.engine.junit5.descriptor.MethodContextImpl.methodContext; import static org.junit.gen5.engine.junit5.descriptor.MethodContextImpl.methodContext;


import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;


import org.junit.gen5.api.AfterAll; import org.junit.gen5.api.AfterAll;
Expand Down Expand Up @@ -99,6 +100,7 @@ public final boolean isContainer() {
public JUnit5EngineExecutionContext prepare(JUnit5EngineExecutionContext context) { public JUnit5EngineExecutionContext prepare(JUnit5EngineExecutionContext context) {
TestExtensionRegistry newExtensionRegistry = populateNewTestExtensionRegistryFromExtendWith(testClass, TestExtensionRegistry newExtensionRegistry = populateNewTestExtensionRegistryFromExtendWith(testClass,
context.getTestExtensionRegistry()); context.getTestExtensionRegistry());

registerBeforeAllMethods(newExtensionRegistry); registerBeforeAllMethods(newExtensionRegistry);
registerAfterAllMethods(newExtensionRegistry); registerAfterAllMethods(newExtensionRegistry);
registerBeforeEachMethods(newExtensionRegistry); registerBeforeEachMethods(newExtensionRegistry);
Expand Down Expand Up @@ -178,67 +180,87 @@ private void invokeAfterAllExtensionPoints(TestExtensionRegistry newTestExtensio
TestExtensionRegistry.ApplicationOrder.BACKWARD).forEach(applyAfterAll); TestExtensionRegistry.ApplicationOrder.BACKWARD).forEach(applyAfterAll);
} }


// TODO Remove duplication with registerAfterAllMethods
private void registerBeforeAllMethods(TestExtensionRegistry extensionRegistry) { private void registerBeforeAllMethods(TestExtensionRegistry extensionRegistry) {
List<Method> beforeAllMethods = findAnnotatedMethods(testClass, BeforeAll.class, MethodSortOrder.HierarchyDown); registerAnnotatedMethodsAsExtensions(extensionRegistry, BeforeAll.class, BeforeAllExtensionPoint.class,
beforeAllMethods.stream().forEach(method -> { this::assertStatic, this::synthesizeBeforeAllExtensionPoint);
if (!ReflectionUtils.isStatic(method)) { }
String message = String.format(
"Cannot register method '%s' as BeforeAll extension since it is not static.", method.getName());
throw new ExtensionConfigurationException(message);
}
BeforeAllExtensionPoint extensionPoint = containerExtensionContext -> {
new MethodInvoker(containerExtensionContext, extensionRegistry).invoke(methodContext(null, method));
};
extensionRegistry.registerExtension(extensionPoint, ExtensionPoint.Position.DEFAULT, method.getName());
});
}

// TODO Remove duplication with registerBeforeAllMethods
private void registerAfterAllMethods(TestExtensionRegistry extensionRegistry) { private void registerAfterAllMethods(TestExtensionRegistry extensionRegistry) {
List<Method> beforeAllMethods = findAnnotatedMethods(testClass, AfterAll.class, MethodSortOrder.HierarchyDown); registerAnnotatedMethodsAsExtensions(extensionRegistry, AfterAll.class, AfterAllExtensionPoint.class,
beforeAllMethods.stream().forEach(method -> { this::assertStatic, this::synthesizeAfterAllExtensionPoint);
if (!ReflectionUtils.isStatic(method)) { }
String message = String.format(
"Cannot register method '%s' as AfterAll extension since it is not static.", method.getName());
throw new ExtensionConfigurationException(message);
}
AfterAllExtensionPoint extensionPoint = containerExtensionContext -> {
new MethodInvoker(containerExtensionContext, extensionRegistry).invoke(methodContext(null, method));
};
extensionRegistry.registerExtension(extensionPoint, ExtensionPoint.Position.DEFAULT, method.getName());
});
}

// TODO Remove duplication with registerAfterEachMethods
private void registerBeforeEachMethods(TestExtensionRegistry extensionRegistry) { private void registerBeforeEachMethods(TestExtensionRegistry extensionRegistry) {
List<Method> beforeEachMethods = findAnnotatedMethods(testClass, BeforeEach.class, registerAnnotatedMethodsAsExtensions(extensionRegistry, BeforeEach.class, BeforeEachExtensionPoint.class,
MethodSortOrder.HierarchyDown); this::assertNonStatic, this::synthesizeBeforeEachExtensionPoint);
beforeEachMethods.stream().forEach(method -> {
BeforeEachExtensionPoint extensionPoint = testExtensionContext -> {
runMethodInTestExtensionContext(method, testExtensionContext, extensionRegistry);
};
extensionRegistry.registerExtension(extensionPoint, ExtensionPoint.Position.DEFAULT, method.getName());
});
} }


// TODO Remove duplication with registerBeforeEachMethods
private void registerAfterEachMethods(TestExtensionRegistry extensionRegistry) { private void registerAfterEachMethods(TestExtensionRegistry extensionRegistry) {
List<Method> afterEachMethods = findAnnotatedMethods(testClass, AfterEach.class, MethodSortOrder.HierarchyDown); registerAnnotatedMethodsAsExtensions(extensionRegistry, AfterEach.class, AfterEachExtensionPoint.class,
afterEachMethods.stream().forEach(method -> { this::assertNonStatic, this::synthesizeAfterEachExtensionPoint);
AfterEachExtensionPoint extensionPoint = testExtensionContext -> { }
runMethodInTestExtensionContext(method, testExtensionContext, extensionRegistry);
}; private void registerAnnotatedMethodsAsExtensions(TestExtensionRegistry extensionRegistry,
extensionRegistry.registerExtension(extensionPoint, ExtensionPoint.Position.DEFAULT, method.getName()); Class<? extends Annotation> annotationType, Class<?> extensionType,
}); BiConsumer<Class<?>, Method> methodValidator,
} BiFunction<TestExtensionRegistry, Method, ExtensionPoint> extensionPointSynthesizer) {


private void runMethodInTestExtensionContext(Method method, TestExtensionContext testExtensionContext, // @formatter:off
TestExtensionRegistry extensionRegistry) { findAnnotatedMethods(testClass, annotationType, MethodSortOrder.HierarchyDown).stream()
Optional<Object> optionalInstance = ReflectionUtils.getOuterInstance(testExtensionContext.getTestInstance(), .peek(method -> methodValidator.accept(extensionType, method))
method.getDeclaringClass()); .forEach(method ->
optionalInstance.ifPresent(instance -> new MethodInvoker(testExtensionContext, extensionRegistry).invoke( extensionRegistry.registerExtension(extensionPointSynthesizer.apply(extensionRegistry, method),
methodContext(instance, method))); ExtensionPoint.Position.DEFAULT, method.getName()));
// @formatter:on
}

private BeforeAllExtensionPoint synthesizeBeforeAllExtensionPoint(TestExtensionRegistry registry, Method method) {
return (BeforeAllExtensionPoint) extensionContext -> {
new MethodInvoker(extensionContext, registry).invoke(methodContext(null, method));
};
}

private AfterAllExtensionPoint synthesizeAfterAllExtensionPoint(TestExtensionRegistry registry, Method method) {
return (AfterAllExtensionPoint) extensionContext -> {
new MethodInvoker(extensionContext, registry).invoke(methodContext(null, method));
};
}

private BeforeEachExtensionPoint synthesizeBeforeEachExtensionPoint(TestExtensionRegistry registry, Method method) {
return (BeforeEachExtensionPoint) extensionContext -> {
runMethodInTestExtensionContext(method, extensionContext, registry);
};
}

private AfterEachExtensionPoint synthesizeAfterEachExtensionPoint(TestExtensionRegistry registry, Method method) {
return (AfterEachExtensionPoint) extensionContext -> {
runMethodInTestExtensionContext(method, extensionContext, registry);
};
}

private void runMethodInTestExtensionContext(Method method, TestExtensionContext context,
TestExtensionRegistry registry) {

// @formatter:off
ReflectionUtils.getOuterInstance(context.getTestInstance(), method.getDeclaringClass())
.ifPresent(instance -> new MethodInvoker(context, registry).invoke(methodContext(instance, method)));
// @formatter:on
}

private void assertStatic(Class<?> extensionType, Method method) {
if (!ReflectionUtils.isStatic(method)) {
String message = String.format("Cannot register method '%s' as a(n) %s since it is not static.",
method.getName(), extensionType.getSimpleName());
throw new ExtensionConfigurationException(message);
}
}

private void assertNonStatic(Class<?> extensionType, Method method) {
if (ReflectionUtils.isStatic(method)) {
String message = String.format("Cannot register method '%s' as a(n) %s since it is static.",
method.getName(), extensionType.getSimpleName());
throw new ExtensionConfigurationException(message);
}
} }


} }

0 comments on commit 452687e

Please sign in to comment.