Skip to content

Commit

Permalink
Before- and AfterEachExtensionPoints added. Before/AfterEach method y…
Browse files Browse the repository at this point in the history
…et to come.

------------------------------------------------------------------------
On behalf of the community, the JUnit Lambda Team thanks
AdNovum Informatik AG (http://www.adnovum.ch)
JUnit crowdfunding campaign!
------------------------------------------------------------------------
  • Loading branch information
jlink committed Dec 13, 2015
1 parent 94bd598 commit e9d19c2
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 39 deletions.
Expand Up @@ -17,7 +17,6 @@
import java.util.List;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.gen5.api.AfterEach;
import org.junit.gen5.api.BeforeEach;
import org.junit.gen5.api.Test;
Expand All @@ -33,8 +32,6 @@
*
* @since 5.0
*/
@Ignore("https://github.com/junit-team/junit-lambda/issues/39")

public class MethodLevelCallbackTests extends AbstractJUnit5TestEngineTestCase {

@org.junit.Test
Expand All @@ -49,25 +46,21 @@ public void beforeEachAndAfterEachCallbacksWithTestInstancePerMethod() {
Assert.assertEquals("# tests aborted", 0, listener.testAbortedCount.get());
Assert.assertEquals("# tests failed", 0, listener.testFailedCount.get());

Assert.assertTrue("@BeforeEach was not invoked", InstancePerMethodTestCase.beforeEachInvoked);
Assert.assertTrue("@AfterEach was not invoked", InstancePerMethodTestCase.afterEachInvoked);

Assert.assertEquals("preBeforeEach()", asList("foo", "bar"), preBeforeEachMethods);
Assert.assertEquals("postAfterEach()", asList("bar", "foo"), postAfterEachMethods);
Assert.assertEquals("wrong before each call sequence", asList("foo", "bar", "method"), beforeEachCalls);
Assert.assertEquals("wrong after each call sequence", asList("method", "bar", "foo"), afterEachCalls);
}

// -------------------------------------------------------------------

private static List<String> beforeEachCalls = new ArrayList<>();
private static List<String> afterEachCalls = new ArrayList<>();

@ExtendWith({ FooMethodLevelCallbacks.class, BarMethodLevelCallbacks.class })
private static class InstancePerMethodTestCase {

static boolean beforeEachInvoked = false;

static boolean afterEachInvoked = false;

@BeforeEach
void beforeEach() {
beforeEachInvoked = true;
beforeEachCalls.add("method");
}

@Test
Expand All @@ -77,24 +70,21 @@ void alwaysPasses() {

@AfterEach
void afterEach() {
afterEachInvoked = true;
afterEachCalls.add("method");
}

}

private static List<String> preBeforeEachMethods = new ArrayList<>();
private static List<String> postAfterEachMethods = new ArrayList<>();

private static class FooMethodLevelCallbacks implements BeforeEachExtensionPoint, AfterEachExtensionPoint {

@Override
public void beforeEach(TestExtensionContext context) {
preBeforeEachMethods.add("foo");
beforeEachCalls.add("foo");
}

@Override
public void afterEach(TestExtensionContext context) {
postAfterEachMethods.add("foo");
afterEachCalls.add("foo");
}

}
Expand All @@ -103,12 +93,12 @@ private static class BarMethodLevelCallbacks implements BeforeEachExtensionPoint

@Override
public void beforeEach(TestExtensionContext context) {
preBeforeEachMethods.add("bar");
beforeEachCalls.add("bar");
}

@Override
public void afterEach(TestExtensionContext context) {
postAfterEachMethods.add("bar");
afterEachCalls.add("bar");
}

}
Expand Down
Expand Up @@ -11,11 +11,14 @@
package org.junit.gen5.engine.junit5.execution;

import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.gen5.api.extension.ExtensionPoint;
import org.junit.gen5.api.extension.ExtensionPoint.Position;
import org.junit.gen5.api.extension.ExtensionRegistrar;
import org.junit.gen5.api.extension.ExtensionRegistry;
import org.junit.gen5.api.extension.MethodParameterResolver;
Expand All @@ -29,17 +32,21 @@ public class TestExtensionRegistryTest {

private TestExtensionRegistry registry;

@Before
public void initRegistry() {
registry = new TestExtensionRegistry();
}

@Test
public void checkJUnit5DefaultExtensions() {
public void checkDefaultExtensions() {
Assert.assertEquals(2, TestExtensionRegistry.getDefaultExtensionClasses().size());

assertDefaultExtensionType(DisabledCondition.class);
assertDefaultExtensionType(TestNameParameterResolver.class);
}

@Test
public void newRegistryWithoutParentHasDefaultExtensions() {
registry = new TestExtensionRegistry();
public void newRegistryWithoutParentHasDefaultExtensions() throws Exception {
Set<Class<? extends TestExtension>> extensions = registry.getRegisteredExtensionClasses();

Assert.assertEquals(TestExtensionRegistry.getDefaultExtensionClasses().size(), extensions.size());
Expand All @@ -52,9 +59,8 @@ public void newRegistryWithoutParentHasDefaultExtensions() {
}

@Test
public void addExtensionPointsByClass() {
public void registerExtensionByImplementingClass() throws Exception {

registry = new TestExtensionRegistry();
registry.addExtension(MyExtension.class);

assertExtensionRegistered(registry, MyExtension.class);
Expand All @@ -74,9 +80,8 @@ public void addExtensionPointsByClass() {
}

@Test
public void addTestExtensionThatImplementsMultipleExtensionPoints() {
public void registerTestExtensionThatImplementsMultipleExtensionPoints() throws Exception {

registry = new TestExtensionRegistry();
registry.addExtension(MultipleExtension.class);

assertExtensionRegistered(registry, MultipleExtension.class);
Expand All @@ -86,7 +91,7 @@ public void addTestExtensionThatImplementsMultipleExtensionPoints() {
}

@Test
public void extensionsAreInheritedFromParent() {
public void extensionsAreInheritedFromParent() throws Exception {

TestExtensionRegistry parent = new TestExtensionRegistry();
parent.addExtension(MyExtension.class);
Expand All @@ -105,20 +110,79 @@ public void extensionsAreInheritedFromParent() {
}

@Test
public void addExtensionPointsByExtensionRegistrar() {
public void registerExtensionPointsByExtensionRegistrar() throws Exception {

registry = new TestExtensionRegistry();
registry.addExtension(MyExtensionRegistrar.class);

assertExtensionRegistered(registry, MyExtensionRegistrar.class);
Assert.assertEquals(1, countExtensionPoints(MyExtensionPoint.class));
Assert.assertEquals(1, countExtensionPoints(AnotherExtensionPoint.class));
}

private int countExtensionPoints(Class<? extends ExtensionPoint> extensionPointType) {
@Test
public void applyExtensionPointsInjectsCorrectRegisteredExceptionPoint() throws Exception {

registry.addExtension(MyExtension.class);

AtomicBoolean hasRun = new AtomicBoolean(false);

registry.applyExtensionPoints(MyExtensionPoint.class, TestExtensionRegistry.ApplicationOrder.FORWARD,
registeredExtensionPoint -> {
Assert.assertEquals(MyExtension.class.getName(), registeredExtensionPoint.getExtensionName());
Assert.assertEquals(Position.DEFAULT, registeredExtensionPoint.getPosition());
Assert.assertTrue(registeredExtensionPoint.getExtensionPoint() instanceof MyExtensionPoint);
hasRun.set(true);
});

Assert.assertTrue(hasRun.get());

}

@Test
public void registerExtensionPointDirectly() throws Exception {

registry.registerExtension((MyExtensionPoint) test -> {
}, Position.INNERMOST, "anonymous extension");

AtomicBoolean hasRun = new AtomicBoolean(false);

registry.applyExtensionPoints(MyExtensionPoint.class, TestExtensionRegistry.ApplicationOrder.FORWARD,
registeredExtensionPoint -> {
Assert.assertEquals("anonymous extension", registeredExtensionPoint.getExtensionName());
Assert.assertEquals(Position.INNERMOST, registeredExtensionPoint.getPosition());
Assert.assertTrue(registeredExtensionPoint.getExtensionPoint() instanceof MyExtensionPoint);
hasRun.set(true);
});

Assert.assertTrue(hasRun.get());

}

@Test
public void exceptionInApplierCodeStopsIterationThroughExtensionPoints() {
registry.registerExtension((MyExtensionPoint) test -> {
}, Position.DEFAULT, "anonymous extension 1");
registry.registerExtension((MyExtensionPoint) test -> {
}, Position.DEFAULT, "anonymous extension 2");

AtomicInteger countCalledExtensions = new AtomicInteger(0);
try {
registry.applyExtensionPoints(MyExtensionPoint.class, TestExtensionRegistry.ApplicationOrder.FORWARD,
registeredExtensionPoint -> {
countCalledExtensions.incrementAndGet();
throw new RuntimeException("should stop iteration");
});
}
catch (RuntimeException expected) {
}
Assert.assertEquals(1, countCalledExtensions.get());

}

private int countExtensionPoints(Class<? extends ExtensionPoint> extensionPointType) throws Exception {
AtomicInteger counter = new AtomicInteger();
registry.applyExtensionPoints(extensionPointType, TestExtensionRegistry.ApplicationOrder.FORWARD,
applier -> counter.incrementAndGet());
registeredExtensionPoint -> counter.incrementAndGet());
return counter.get();
}

Expand Down
Expand Up @@ -17,9 +17,12 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

import org.junit.gen5.api.AfterEach;
import org.junit.gen5.api.BeforeEach;
import org.junit.gen5.api.extension.AfterEachExtensionPoint;
import org.junit.gen5.api.extension.BeforeEachExtensionPoint;
import org.junit.gen5.commons.util.Preconditions;
import org.junit.gen5.commons.util.ReflectionUtils;
import org.junit.gen5.commons.util.ReflectionUtils.MethodSortOrder;
Expand All @@ -31,13 +34,14 @@
import org.junit.gen5.engine.junit5.execution.BeforeEachCallback;
import org.junit.gen5.engine.junit5.execution.JUnit5EngineExecutionContext;
import org.junit.gen5.engine.junit5.execution.MethodInvoker;
import org.junit.gen5.engine.junit5.execution.RegisteredExtensionPoint;
import org.junit.gen5.engine.junit5.execution.TestExtensionRegistry;
import org.junit.gen5.engine.junit5.execution.TestInstanceProvider;

/**
* {@link TestDescriptor} for tests based on Java classes.
*
* <p>The pattern of the {@link #getUniqueId unique ID} takes the form of
* <p>
* The pattern of the {@link #getUniqueId unique ID} takes the form of
* <code>{parent unique id}:{fully qualified class name}</code>.
*
* @since 5.0
Expand Down Expand Up @@ -85,12 +89,13 @@ public boolean isContainer() {

@Override
public JUnit5EngineExecutionContext beforeAll(JUnit5EngineExecutionContext context) {
context = context.extend().withTestExtensionRegistry(
populateNewTestExtensionRegistryFromExtendWith(testClass, context.getTestExtensionRegistry())).build();
// @formatter:off
return context.extend()
.withTestInstanceProvider(testInstanceProvider(context))
.withBeforeEachCallback(beforeEachCallback(context))
.withAfterEachCallback(afterEachCallback(context))
.withTestExtensionRegistry(populateNewTestExtensionRegistryFromExtendWith(testClass, context.getTestExtensionRegistry()))
.withExtensionContext(new ClassBasedContainerExtensionContext(context.getExtensionContext(), this))
.build();
// @formatter:on
Expand All @@ -103,8 +108,20 @@ protected TestInstanceProvider testInstanceProvider(JUnit5EngineExecutionContext
protected BeforeEachCallback beforeEachCallback(JUnit5EngineExecutionContext context) {
List<Method> beforeEachMethods = findAnnotatedMethods(testClass, BeforeEach.class,
MethodSortOrder.HierarchyDown);
TestExtensionRegistry extensionRegistry = context.getTestExtensionRegistry();
return (testExtensionContext, testInstance) -> {
Consumer<RegisteredExtensionPoint<BeforeEachExtensionPoint>> applyBeforeEach = registeredExtensionPoint -> {
try {
registeredExtensionPoint.getExtensionPoint().beforeEach(testExtensionContext);
}
catch (Exception e) { //TODO: Non RTEs should be allowed
throw new RuntimeException(e);
}
};
TestExtensionRegistry extensionRegistry = context.getTestExtensionRegistry();
extensionRegistry.applyExtensionPoints(BeforeEachExtensionPoint.class,
TestExtensionRegistry.ApplicationOrder.FORWARD, applyBeforeEach);

//TODO: Register beforeEachMethods as extension points to enable correct sorting
for (Method method : beforeEachMethods) {
new MethodInvoker(testExtensionContext, extensionRegistry).invoke(methodContext(testInstance, method));
}
Expand All @@ -113,10 +130,12 @@ protected BeforeEachCallback beforeEachCallback(JUnit5EngineExecutionContext con

protected AfterEachCallback afterEachCallback(JUnit5EngineExecutionContext context) {
List<Method> afterEachMethods = findAnnotatedMethods(testClass, AfterEach.class, MethodSortOrder.HierarchyUp);
TestExtensionRegistry extensionRegistry = context.getTestExtensionRegistry();
return (testExtensionContext, testInstance, throwable) -> {
TestExtensionRegistry extensionRegistry = context.getTestExtensionRegistry();
List<Throwable> throwables = new LinkedList<>();
throwable.ifPresent(throwables::add);

//TODO: Register afterEachMethods as extension points to enable correct sorting
for (Method method : afterEachMethods) {
try {
new MethodInvoker(testExtensionContext, extensionRegistry).invoke(
Expand All @@ -126,6 +145,18 @@ protected AfterEachCallback afterEachCallback(JUnit5EngineExecutionContext conte
throwables.add(t);
}
}

Consumer<RegisteredExtensionPoint<AfterEachExtensionPoint>> applyAfterEach = registeredExtensionPoint -> {
try {
registeredExtensionPoint.getExtensionPoint().afterEach(testExtensionContext);
}
catch (Exception e) {
throwables.add(e);
}
};
extensionRegistry.applyExtensionPoints(AfterEachExtensionPoint.class,
TestExtensionRegistry.ApplicationOrder.BACKWARD, applyAfterEach);

if (!throwables.isEmpty()) {
Throwable t = throwables.get(0);
throwables.stream().skip(1).forEach(t::addSuppressed);
Expand Down
Expand Up @@ -173,7 +173,7 @@ private void registerExtensionPointImplementors(TestExtension testExtension) {
}
}

private <E extends ExtensionPoint> void registerExtension(E extension, Position position, String extensionName) {
public <E extends ExtensionPoint> void registerExtension(E extension, Position position, String extensionName) {
RegisteredExtensionPoint<E> registeredExtensionPoint = new RegisteredExtensionPoint<>(extension, position,
extensionName);
registeredExtensionPoints.add(registeredExtensionPoint);
Expand Down

0 comments on commit e9d19c2

Please sign in to comment.