Skip to content

Commit

Permalink
Merge pull request #27019 from geoand/#26999
Browse files Browse the repository at this point in the history
Introduce a new set of test callbacks used right before and after test execution
  • Loading branch information
gsmet authored Aug 2, 2022
2 parents 0e5d285 + 52a4b3e commit f2e4c80
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/src/main/asciidoc/getting-started-testing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ Alternatively or additionally to an interceptor, you can enrich *all* your `@Qua
* `io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback`
* `io.quarkus.test.junit.callback.QuarkusTestAfterConstructCallback`
* `io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback`
* `io.quarkus.test.junit.callback.QuarkusTestBeforeTestExecutionCallback`
* `io.quarkus.test.junit.callback.QuarkusTestAfterTestExecutionCallback`
* `io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback`

Such a callback implementation has to be registered as a "service provider" as defined by `java.util.ServiceLoader`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.quarkus.it.main;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class QuarkusBeforeAndAfterTestCallbacksTest {

@BeforeEach
@AfterEach
public void ensureMissingSystemProperty() {
assertNull(System.getProperty("quarkus.test.method"));
}

@Test
public void actualTest() {
assertEquals("actualTest", System.getProperty("quarkus.test.method"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.quarkus.it.main;

import io.quarkus.test.junit.callback.QuarkusTestAfterTestExecutionCallback;
import io.quarkus.test.junit.callback.QuarkusTestMethodContext;

public class SystemPropertySetterAfterTestExecutionCallback implements QuarkusTestAfterTestExecutionCallback {

@Override
public void afterTestExecution(QuarkusTestMethodContext context) {
System.clearProperty("quarkus.test.method");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.quarkus.it.main;

import io.quarkus.test.junit.callback.QuarkusTestBeforeTestExecutionCallback;
import io.quarkus.test.junit.callback.QuarkusTestMethodContext;

public class SystemPropertySetterBeforeTestExecutionCallback implements QuarkusTestBeforeTestExecutionCallback {

@Override
public void beforeTestExecution(QuarkusTestMethodContext context) {
System.setProperty("quarkus.test.method", context.getTestMethod().getName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.it.main.SystemPropertySetterAfterTestExecutionCallback
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.it.main.SystemPropertySetterBeforeTestExecutionCallback
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
Expand Down Expand Up @@ -102,15 +104,18 @@
import io.quarkus.test.junit.callback.QuarkusTestAfterAllCallback;
import io.quarkus.test.junit.callback.QuarkusTestAfterConstructCallback;
import io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback;
import io.quarkus.test.junit.callback.QuarkusTestAfterTestExecutionCallback;
import io.quarkus.test.junit.callback.QuarkusTestBeforeClassCallback;
import io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback;
import io.quarkus.test.junit.callback.QuarkusTestBeforeTestExecutionCallback;
import io.quarkus.test.junit.callback.QuarkusTestContext;
import io.quarkus.test.junit.callback.QuarkusTestMethodContext;
import io.quarkus.test.junit.internal.DeepClone;
import io.quarkus.test.junit.internal.SerializationWithXStreamFallbackDeepClone;

public class QuarkusTestExtension extends AbstractJvmQuarkusTestExtension
implements BeforeEachCallback, AfterEachCallback, BeforeAllCallback, InvocationInterceptor, AfterAllCallback,
implements BeforeEachCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, AfterEachCallback,
BeforeAllCallback, InvocationInterceptor, AfterAllCallback,
ParameterResolver, ExecutionCondition {

private static final Logger log = Logger.getLogger(QuarkusTestExtension.class);
Expand All @@ -131,6 +136,8 @@ public class QuarkusTestExtension extends AbstractJvmQuarkusTestExtension
private static List<Object> beforeClassCallbacks;
private static List<Object> afterConstructCallbacks;
private static List<Object> beforeEachCallbacks;
private static List<Object> beforeTestCallbacks;
private static List<Object> afterTestCallbacks;
private static List<Object> afterEachCallbacks;
private static List<Object> afterAllCallbacks;
private static Class<?> quarkusTestMethodContextClass;
Expand Down Expand Up @@ -353,6 +360,8 @@ private void populateCallbacks(ClassLoader classLoader) throws ClassNotFoundExce
beforeClassCallbacks = new ArrayList<>();
afterConstructCallbacks = new ArrayList<>();
beforeEachCallbacks = new ArrayList<>();
beforeTestCallbacks = new ArrayList<>();
afterTestCallbacks = new ArrayList<>();
afterEachCallbacks = new ArrayList<>();
afterAllCallbacks = new ArrayList<>();

Expand All @@ -371,6 +380,16 @@ private void populateCallbacks(ClassLoader classLoader) throws ClassNotFoundExce
for (Object quarkusTestBeforeEachCallback : quarkusTestBeforeEachLoader) {
beforeEachCallbacks.add(quarkusTestBeforeEachCallback);
}
ServiceLoader<?> quarkusTestBeforeTestLoader = ServiceLoader
.load(Class.forName(QuarkusTestBeforeTestExecutionCallback.class.getName(), false, classLoader), classLoader);
for (Object quarkusTestBeforeTestCallback : quarkusTestBeforeTestLoader) {
beforeTestCallbacks.add(quarkusTestBeforeTestCallback);
}
ServiceLoader<?> quarkusTestAfterTestLoader = ServiceLoader
.load(Class.forName(QuarkusTestAfterTestExecutionCallback.class.getName(), false, classLoader), classLoader);
for (Object quarkusTestAfterTestCallback : quarkusTestAfterTestLoader) {
afterTestCallbacks.add(quarkusTestAfterTestCallback);
}
ServiceLoader<?> quarkusTestAfterEachLoader = ServiceLoader
.load(Class.forName(QuarkusTestAfterEachCallback.class.getName(), false, classLoader), classLoader);
for (Object quarkusTestAfterEach : quarkusTestAfterEachLoader) {
Expand All @@ -396,6 +415,30 @@ private void populateTestMethodInvokers(ClassLoader quarkusClassLoader) {
}
}

@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
if (isNativeOrIntegrationTest(context.getRequiredTestClass()) || beforeTestCallbacks.isEmpty()) {
return;
}
if (!failedBoot) {
ClassLoader original = setCCL(runningQuarkusApplication.getClassLoader());
try {
for (Object beforeTestCallback : beforeTestCallbacks) {
Map.Entry<Class<?>, ?> tuple = createQuarkusTestMethodContextTuple(context);
beforeTestCallback.getClass().getMethod("beforeTestExecution", tuple.getKey())
.invoke(beforeTestCallback, tuple.getValue());
}
} catch (InvocationTargetException e) {
throw e.getCause() instanceof Exception ? (Exception) e.getCause() : e;
} finally {
setCCL(original);
}
} else {
throwBootFailureException();
return;
}
}

@Override
public void beforeEach(ExtensionContext context) throws Exception {
if (isNativeOrIntegrationTest(context.getRequiredTestClass())) {
Expand Down Expand Up @@ -500,6 +543,27 @@ private static String sanitizeEndpointPath(String path) {
return replaced.toString();
}

@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
if (isNativeOrIntegrationTest(context.getRequiredTestClass()) || afterTestCallbacks.isEmpty()) {
return;
}
if (!failedBoot) {
ClassLoader original = setCCL(runningQuarkusApplication.getClassLoader());
try {
for (Object afterTestCallback : afterTestCallbacks) {
Map.Entry<Class<?>, ?> tuple = createQuarkusTestMethodContextTuple(context);
afterTestCallback.getClass().getMethod("afterTestExecution", tuple.getKey())
.invoke(afterTestCallback, tuple.getValue());
}
} catch (InvocationTargetException e) {
throw e.getCause() instanceof Exception ? (Exception) e.getCause() : e;
} finally {
setCCL(original);
}
}
}

@Override
public void afterEach(ExtensionContext context) throws Exception {
if (isNativeOrIntegrationTest(context.getRequiredTestClass())) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.test.junit.callback;

/**
* Can be implemented by classes that shall be called immediately after a test method in a {@code @QuarkusTest}.
* These callbacks run before {@link QuarkusTestAfterEachCallback} callbacks and are usually accompanied by
* {@link QuarkusTestBeforeTestExecutionCallback}.
* <p>
* The implementing class has to be {@linkplain java.util.ServiceLoader deployed as service provider on the class path}.
*/
public interface QuarkusTestAfterTestExecutionCallback {

void afterTestExecution(QuarkusTestMethodContext context);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.test.junit.callback;

/**
* Can be implemented by classes that shall be called right before a test method in a {@code @QuarkusTest}.
* These callbacks run after {@link QuarkusTestBeforeEachCallback} callbacks and are usually accompanied by
* {@link QuarkusTestAfterTestExecutionCallback}.
* <p>
* The implementing class has to be {@linkplain java.util.ServiceLoader deployed as service provider on the class path}.
*/
public interface QuarkusTestBeforeTestExecutionCallback {

void beforeTestExecution(QuarkusTestMethodContext context);
}

0 comments on commit f2e4c80

Please sign in to comment.