Skip to content

Commit

Permalink
Ensure test-callbacks are removed when switching from @QuarkusTest
Browse files Browse the repository at this point in the history
…to `@QuarkusIntegrationTest`

In case there are both test classes annotated with `@QuarkusTest` and `@QuarkusIntegrationTest`, JUnit callbacks (those in `AbstractTestWithCallbacksExtension`) are not properly cleaned up, causing the (later) run integration tests to try to call the "old" callbacks, which cannot work (class loader issue). This change adds a `Runnable` to clean up the memoized callbacks in `QuarkusTestExtensionState.close()`, which works for both `IntegrationTestExtensionState` and `QuarkusTestExtension.ExtensionState`.
  • Loading branch information
snazy committed Nov 4, 2024
1 parent ac87489 commit 54f8235
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,18 @@ protected void invokeAfterAllCallbacks(Class<?> clazz, Object testContext) throw
invokeCallbacks(afterAllCallbacks, "afterAll", clazz, testContext);
}

protected void populateCallbacks(ClassLoader classLoader) throws ClassNotFoundException {
protected static void clearCallbacks() {
beforeClassCallbacks = new ArrayList<>();
afterConstructCallbacks = new ArrayList<>();
beforeEachCallbacks = new ArrayList<>();
beforeTestCallbacks = new ArrayList<>();
afterTestCallbacks = new ArrayList<>();
afterEachCallbacks = new ArrayList<>();
afterAllCallbacks = new ArrayList<>();
}

protected void populateCallbacks(ClassLoader classLoader) throws ClassNotFoundException {
clearCallbacks();

ServiceLoader<?> quarkusTestBeforeClassLoader = ServiceLoader
.load(Class.forName(QuarkusTestBeforeClassCallback.class.getName(), false, classLoader), classLoader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

public class IntegrationTestExtensionState extends QuarkusTestExtensionState {

private Map<String, String> sysPropRestore;
private final Map<String, String> sysPropRestore;

public IntegrationTestExtensionState(TestResourceManager testResourceManager, Closeable resource,
Map<String, String> sysPropRestore) {
super(testResourceManager, resource);
Runnable clearCallbacks, Map<String, String> sysPropRestore) {
super(testResourceManager, resource, clearCallbacks);
this.sysPropRestore = sysPropRestore;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@
import static io.quarkus.test.junit.IntegrationTestUtil.handleDevServices;
import static io.quarkus.test.junit.IntegrationTestUtil.readQuarkusArtifactProperties;
import static io.quarkus.test.junit.IntegrationTestUtil.startLauncher;
import static io.quarkus.test.junit.TestResourceUtil.testResourcesRequireReload;
import static io.quarkus.test.junit.TestResourceUtil.TestResourceManagerReflections.copyEntriesFromProfile;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.time.Duration;
Expand Down Expand Up @@ -108,7 +106,6 @@ public void beforeTestExecution(ExtensionContext context) throws Exception {

} else {
throwBootFailureException();
return;
}
}

Expand Down Expand Up @@ -305,7 +302,7 @@ public void close() throws Throwable {
Closeable resource = new IntegrationTestExtensionStateResource(launcher,
devServicesLaunchResult.getCuratedApplication());
IntegrationTestExtensionState state = new IntegrationTestExtensionState(testResourceManager, resource,
sysPropRestore);
AbstractTestWithCallbacksExtension::clearCallbacks, sysPropRestore);
testHttpEndpointProviders = TestHttpEndpointProvider.load();

return state;
Expand Down Expand Up @@ -467,7 +464,7 @@ public IntegrationTestExtensionStateResource(ArtifactLauncher<?> launcher,
}

@Override
public void close() throws IOException {
public void close() {
if (launcher != null) {
try {
launcher.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static io.quarkus.test.junit.IntegrationTestUtil.activateLogging;

import java.io.Closeable;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.reflect.Constructor;
Expand Down Expand Up @@ -272,7 +271,7 @@ public Thread newThread(Runnable r) {

Closeable shutdownTask = new Closeable() {
@Override
public void close() throws IOException {
public void close() {
TracingHandler.quarkusStopping();
try {
runningQuarkusApplication.close();
Expand All @@ -295,8 +294,7 @@ public void close() throws IOException {
}
}
};
ExtensionState state = new ExtensionState(testResourceManager, shutdownTask);
return state;
return new ExtensionState(testResourceManager, shutdownTask, AbstractTestWithCallbacksExtension::clearCallbacks);
} catch (Throwable e) {
if (!InitialConfigurator.DELAYED_HANDLER.isActivated()) {
activateLogging();
Expand Down Expand Up @@ -1176,12 +1174,12 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con

public static class ExtensionState extends QuarkusTestExtensionState {

public ExtensionState(Closeable testResourceManager, Closeable resource) {
super(testResourceManager, resource);
public ExtensionState(Closeable testResourceManager, Closeable resource, Runnable clearCallbacks) {
super(testResourceManager, resource, clearCallbacks);
}

@Override
protected void doClose() throws IOException {
protected void doClose() {
ClassLoader old = Thread.currentThread().getContextClassLoader();
if (runningQuarkusApplication != null) {
Thread.currentThread().setContextClassLoader(runningQuarkusApplication.getClassLoader());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ public class QuarkusTestExtensionState implements ExtensionContext.Store.Closeab
protected final Closeable testResourceManager;
protected final Closeable resource;
private final Thread shutdownHook;
private final Runnable clearCallbacks;
private Throwable testErrorCause;

public QuarkusTestExtensionState(Closeable testResourceManager, Closeable resource) {
public QuarkusTestExtensionState(Closeable testResourceManager, Closeable resource, Runnable clearCallbacks) {
this.testResourceManager = testResourceManager;
this.resource = resource;
this.clearCallbacks = clearCallbacks;
this.shutdownHook = new Thread(new Runnable() {
@Override
public void run() {
Expand All @@ -40,6 +42,7 @@ public Throwable getTestErrorCause() {
public void close() throws IOException {
if (closed.compareAndSet(false, true)) {
doClose();
clearCallbacks.run();

try {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
Expand Down

0 comments on commit 54f8235

Please sign in to comment.