Skip to content

Commit

Permalink
Revert "Refine TestInstancePostProcessor API regarding access to test…
Browse files Browse the repository at this point in the history
… instance"

This reverts commit 1d30b76, reversing
changes made to 3640af5.
  • Loading branch information
sbrannen committed Jul 4, 2017
1 parent a97e4d3 commit fa7f256
Show file tree
Hide file tree
Showing 22 changed files with 145 additions and 214 deletions.
4 changes: 0 additions & 4 deletions documentation/src/docs/asciidoc/release-notes-5.0.0-M5.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,6 @@ is placed on the Java 9 module path.
* `TestExecutionCondition` and `ContainerExecutionCondition` have been replaced by a
single, general purpose extension API for conditional test execution:
`ExecutionCondition`.
* The `postProcessTestInstance()` method in the `TestInstancePostProcessor` API is no
longer supplied a direct reference to the test instance. However, the test instance
can now be retrieved from the supplied `ExtensionContext` via its
`Optional<Object> getTestInstance()` method.

[[release-notes-5.0.0-m5-migration-extension-api]]
.Extension API Migration
Expand Down
3 changes: 1 addition & 2 deletions documentation/src/test/java/example/TestInfoDemo.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
class TestInfoDemo {

TestInfoDemo(TestInfo testInfo) {
String displayName = testInfo.getDisplayName();
assertTrue(displayName.equals("TEST 1") || displayName.equals("test2()"));
assertEquals("TestInfo Demo", testInfo.getDisplayName());
}

@BeforeEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,16 @@
* <p>Implementations must provide a no-args constructor.
*
* @since 5.0
* @see #postProcessTestInstance(ExtensionContext)
*/
@API(Experimental)
public interface TestInstancePostProcessor extends Extension {

/**
* Callback for post-processing the test instance in the supplied
* {@link ExtensionContext}.
* Callback for post-processing the supplied test instance.
*
* @param testInstance the instance to post-process; never {@code null}
* @param context the current extension context; never {@code null}
* @see ExtensionContext#getTestInstance()
*/
void postProcessTestInstance(ExtensionContext context) throws Exception;
void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception;

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.junit.jupiter.engine.execution;
package org.junit.jupiter.engine.descriptor;

import static java.util.stream.Collectors.toCollection;
import static org.junit.platform.commons.meta.API.Usage.Internal;

import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.meta.API;
import org.junit.jupiter.engine.execution.ExtensionValuesStore;
import org.junit.jupiter.engine.execution.NamespaceAwareStore;
import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.engine.EngineExecutionListener;
import org.junit.platform.engine.TestDescriptor;
Expand All @@ -29,28 +29,25 @@
/**
* @since 5.0
*/
@API(Internal)
public abstract class AbstractExtensionContext<T extends TestDescriptor> implements ExtensionContext {
abstract class AbstractExtensionContext<T extends TestDescriptor> implements ExtensionContext {

private final ExtensionContext parent;
private final EngineExecutionListener engineExecutionListener;
private final T testDescriptor;
private final ExtensionValuesStore valuesStore;

private Object testInstance;

protected AbstractExtensionContext(AbstractExtensionContext<?> parent,
EngineExecutionListener engineExecutionListener, T testDescriptor) {
AbstractExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener,
T testDescriptor) {
this.parent = parent;
this.engineExecutionListener = engineExecutionListener;
this.testDescriptor = testDescriptor;
this.valuesStore = createStore(parent);
}

private ExtensionValuesStore createStore(AbstractExtensionContext<?> parent) {
private ExtensionValuesStore createStore(ExtensionContext parent) {
ExtensionValuesStore parentStore = null;
if (parent != null) {
parentStore = parent.valuesStore;
parentStore = ((AbstractExtensionContext<?>) parent).valuesStore;
}
return new ExtensionValuesStore(parentStore);
}
Expand All @@ -65,15 +62,6 @@ public String getDisplayName() {
return getTestDescriptor().getDisplayName();
}

public void setTestInstance(Object testInstance) {
this.testInstance = testInstance;
}

@Override
public Optional<Object> getTestInstance() {
return Optional.ofNullable(this.testInstance);
}

@Override
public void publishReportEntry(Map<String, String> values) {
engineExecutionListener.reportingEntryPublished(this.testDescriptor, ReportEntry.from(values));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import java.lang.reflect.Method;
import java.util.Optional;

import org.junit.jupiter.engine.execution.AbstractExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.engine.execution.ThrowableCollector;
import org.junit.platform.commons.meta.API;
import org.junit.platform.engine.EngineExecutionListener;
Expand All @@ -28,8 +28,9 @@
public final class ClassExtensionContext extends AbstractExtensionContext<ClassTestDescriptor> {

private final ThrowableCollector throwableCollector;
private Object testInstance;

public ClassExtensionContext(AbstractExtensionContext<?> parent, EngineExecutionListener engineExecutionListener,
public ClassExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener,
ClassTestDescriptor testDescriptor, ThrowableCollector throwableCollector) {

super(parent, engineExecutionListener, testDescriptor);
Expand All @@ -46,6 +47,15 @@ public Optional<Class<?>> getTestClass() {
return Optional.of(getTestDescriptor().getTestClass());
}

void setTestInstance(Object testInstance) {
this.testInstance = testInstance;
}

@Override
public Optional<Object> getTestInstance() {
return Optional.ofNullable(this.testInstance);
}

@Override
public Optional<Method> getTestMethod() {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;

import org.junit.jupiter.api.TestInstance;
Expand All @@ -31,7 +32,6 @@
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
import org.junit.jupiter.engine.execution.AbstractExtensionContext;
import org.junit.jupiter.engine.execution.AfterEachMethodAdapter;
import org.junit.jupiter.engine.execution.BeforeEachMethodAdapter;
import org.junit.jupiter.engine.execution.ExecutableInvoker;
Expand Down Expand Up @@ -176,50 +176,39 @@ private TestInstanceProvider testInstanceProvider(JupiterEngineExecutionContext
if (this.lifecycle == Lifecycle.PER_CLASS) {
// Eagerly load test instance for BeforeAllCallbacks, if necessary,
// and store the instance in the ExtensionContext.
// Note: as a side effect, instantiateAndPostProcessTestInstance() also stores
// the instance it creates in the "current" extension context.
Object instance = instantiateAndPostProcessTestInstance(parentExecutionContext, extensionContext, registry);

// Return a TestInstanceProvider that additionally sets the test instance
// in the supplied child extension context (e.g., a MethodExtensionContext).
return (childContext, childRegistry) -> {
childContext.setTestInstance(instance);
return instance;
};
Object instance = instantiateAndPostProcessTestInstance(parentExecutionContext, extensionContext, registry,
extensionContext::setTestInstance);
return childRegistry -> instance;
}

// else Lifecycle.PER_METHOD
return (childContext, childRegistry) -> instantiateAndPostProcessTestInstance(parentExecutionContext,
childContext, childRegistry.orElse(registry));
return childRegistry -> instantiateAndPostProcessTestInstance(parentExecutionContext, extensionContext,
childRegistry.orElse(registry), instance -> {
// no extension context update required
});
}

/**
* Instantiate the test instance; set the test instance in the supplied
* extension context; and post process the test instance.
*
* @see #instantiateTestClass
* @see AbstractExtensionContext#setTestInstance
* @see #invokeTestInstancePostProcessors
*/
private Object instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext context,
AbstractExtensionContext<?> extensionContext, ExtensionRegistry registry) {
ExtensionContext extensionContext, ExtensionRegistry registry, Consumer<Object> testInstanceConsumer) {

Object instance = instantiateTestClass(context, registry, extensionContext);
extensionContext.setTestInstance(instance);
invokeTestInstancePostProcessors(registry, extensionContext);
testInstanceConsumer.accept(instance);
invokeTestInstancePostProcessors(instance, registry, extensionContext);
return instance;
}

protected Object instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext,
ExtensionRegistry registry, AbstractExtensionContext<?> extensionContext) {
ExtensionRegistry registry, ExtensionContext extensionContext) {

Constructor<?> constructor = ReflectionUtils.getDeclaredConstructor(this.testClass);
return executableInvoker.invoke(constructor, extensionContext, registry);
}

private void invokeTestInstancePostProcessors(ExtensionRegistry registry, ExtensionContext context) {
private void invokeTestInstancePostProcessors(Object instance, ExtensionRegistry registry,
ExtensionContext context) {

registry.stream(TestInstancePostProcessor.class).forEach(
extension -> executeAndMaskThrowable(() -> extension.postProcessTestInstance(context)));
extension -> executeAndMaskThrowable(() -> extension.postProcessTestInstance(instance, context)));
}

private void invokeBeforeAllCallbacks(JupiterEngineExecutionContext context) {
Expand Down Expand Up @@ -300,6 +289,7 @@ private AfterEachMethodAdapter synthesizeAfterEachMethodAdapter(Method method) {
}

private void invokeMethodInExtensionContext(Method method, ExtensionContext context, ExtensionRegistry registry) {

Object testInstance = context.getTestInstance().orElseThrow(() -> new JUnitException(
"Illegal state: test instance not present for method: " + method.toGenericString()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import static org.junit.jupiter.engine.extension.ExtensionRegistry.createRegistryWithDefaultExtensions;
import static org.junit.platform.commons.meta.API.Usage.Internal;

import org.junit.jupiter.engine.execution.AbstractExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistry;
import org.junit.platform.commons.meta.API;
Expand All @@ -36,7 +36,7 @@ public JupiterEngineDescriptor(UniqueId uniqueId) {
public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) throws Exception {
ExtensionRegistry extensionRegistry = createRegistryWithDefaultExtensions(context.getConfigurationParameters());
EngineExecutionListener executionListener = context.getExecutionListener();
AbstractExtensionContext<?> extensionContext = new JupiterEngineExtensionContext(executionListener, this);
ExtensionContext extensionContext = new JupiterEngineExtensionContext(executionListener, this);

// @formatter:off
return context.extend()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.lang.reflect.Method;
import java.util.Optional;

import org.junit.jupiter.engine.execution.AbstractExtensionContext;
import org.junit.platform.commons.meta.API;
import org.junit.platform.engine.EngineExecutionListener;

Expand All @@ -41,6 +40,11 @@ public Optional<Class<?>> getTestClass() {
return Optional.empty();
}

@Override
public Optional<Object> getTestInstance() {
return Optional.empty();
}

@Override
public Optional<Method> getTestMethod() {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import java.lang.reflect.Method;
import java.util.Optional;

import org.junit.jupiter.engine.execution.AbstractExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.engine.execution.ThrowableCollector;
import org.junit.platform.commons.meta.API;
import org.junit.platform.engine.EngineExecutionListener;
Expand All @@ -27,13 +27,16 @@
@API(Internal)
public final class MethodExtensionContext extends AbstractExtensionContext<MethodTestDescriptor> {

private final Object testInstance;

private final ThrowableCollector throwableCollector;

public MethodExtensionContext(AbstractExtensionContext<?> parent, EngineExecutionListener engineExecutionListener,
MethodTestDescriptor testDescriptor, ThrowableCollector throwableCollector) {
public MethodExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener,
MethodTestDescriptor testDescriptor, Object testInstance, ThrowableCollector throwableCollector) {

super(parent, engineExecutionListener, testDescriptor);

this.testInstance = testInstance;
this.throwableCollector = throwableCollector;
}

Expand All @@ -52,6 +55,11 @@ public Optional<Method> getTestMethod() {
return Optional.of(getTestDescriptor().getTestMethod());
}

@Override
public Optional<Object> getTestInstance() {
return Optional.of(this.testInstance);
}

@Override
public Optional<Throwable> getExecutionException() {
return Optional.ofNullable(this.throwableCollector.getThrowable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.engine.execution.AbstractExtensionContext;
import org.junit.jupiter.engine.execution.AfterEachMethodAdapter;
import org.junit.jupiter.engine.execution.BeforeEachMethodAdapter;
import org.junit.jupiter.engine.execution.ExecutableInvoker;
Expand Down Expand Up @@ -79,15 +78,10 @@ public Type getType() {
@Override
public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) throws Exception {
ExtensionRegistry registry = populateNewExtensionRegistry(context);
Object testInstance = context.getTestInstanceProvider().getTestInstance(Optional.of(registry));
ThrowableCollector throwableCollector = new ThrowableCollector();
AbstractExtensionContext<?> extensionContext = new MethodExtensionContext(context.getExtensionContext(),
context.getExecutionListener(), this, throwableCollector);

// Even though we (intentionally) ignore the return value, the following line
// is required since the configured TestInstanceProvider is responsible for
// setting the test instance in the supplied extension context.
// See ClassTestDescriptor#testInstanceProvider(...) for details.
context.getTestInstanceProvider().getTestInstance(extensionContext, Optional.of(registry));
ExtensionContext extensionContext = new MethodExtensionContext(context.getExtensionContext(),
context.getExecutionListener(), this, testInstance, throwableCollector);

// @formatter:off
return context.extend()
Expand All @@ -105,7 +99,6 @@ protected ExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionC
@Override
public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context,
DynamicTestExecutor dynamicTestExecutor) throws Exception {

ThrowableCollector throwableCollector = context.getThrowableCollector();

// @formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import java.util.Optional;
import java.util.Set;

import org.junit.jupiter.engine.execution.AbstractExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.engine.execution.ExecutableInvoker;
import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext;
import org.junit.jupiter.engine.extension.ExtensionRegistry;
Expand Down Expand Up @@ -58,11 +58,11 @@ public final Set<TestTag> getTags() {

@Override
protected Object instantiateTestClass(JupiterEngineExecutionContext parentExecutionContext,
ExtensionRegistry registry, AbstractExtensionContext<?> extensionContext) {
ExtensionRegistry registry, ExtensionContext extensionContext) {

// Extensions registered for nested classes and below are not to be used for instantiating outer classes
Optional<ExtensionRegistry> childExtensionRegistryForOuterInstance = Optional.empty();
Object outerInstance = parentExecutionContext.getTestInstanceProvider().getTestInstance(extensionContext,
Object outerInstance = parentExecutionContext.getTestInstanceProvider().getTestInstance(
childExtensionRegistryForOuterInstance);
Constructor<?> constructor = ReflectionUtils.getDeclaredConstructor(getTestClass());
return executableInvoker.invoke(constructor, outerInstance, extensionContext, registry);
Expand Down
Loading

0 comments on commit fa7f256

Please sign in to comment.