From 83c944e66933861670d0d6890c38275dfe05cfdb Mon Sep 17 00:00:00 2001 From: Alex Ch Date: Sun, 1 Mar 2026 13:17:41 +0100 Subject: [PATCH 1/3] Update PlayJUnitExtension.java with new implementation --- .../src/play/test/PlayJUnitExtension.java | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/framework/src/play/test/PlayJUnitExtension.java b/framework/src/play/test/PlayJUnitExtension.java index 46bc8d08f8..1290bfba1e 100644 --- a/framework/src/play/test/PlayJUnitExtension.java +++ b/framework/src/play/test/PlayJUnitExtension.java @@ -5,17 +5,21 @@ import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; +import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import play.Invoker; import play.Invoker.DirectInvocation; import play.Play; +import java.lang.reflect.Method; -public class PlayJUnitExtension implements BeforeAllCallback, BeforeEachCallback, TestExecutionExceptionHandler { +public class PlayJUnitExtension implements BeforeAllCallback, BeforeEachCallback, InvocationInterceptor, TestExecutionExceptionHandler { public static final String invocationType = "JUnitTest"; public static boolean useCustomRunner = false; + private static final ThreadLocal invocationContext = ThreadLocal.withInitial(() -> null); @Override public void beforeAll(ExtensionContext context) throws Exception { @@ -34,7 +38,6 @@ public void beforeAll(ExtensionContext context) throws Exception { TestEngine.initTest(testClass); } - @Override public void beforeEach(ExtensionContext context) throws Exception { if (useCustomRunner) { @@ -42,16 +45,39 @@ public void beforeEach(ExtensionContext context) throws Exception { Play.forceProd = true; Play.init(new File("."), getPlayId()); } + // Store invocation context in ThreadLocal for use in interceptTestMethod + invocationContext.set(new Invoker.InvocationContext(invocationType)); + } + } + + @Override + public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { + if (useCustomRunner) { + // Run the test method within the Play thread context + Invoker.InvocationContext ctx = new Invoker.InvocationContext(invocationType); + Throwable[] testException = new Throwable[1]; + Invoker.invokeInThread(new DirectInvocation() { @Override public void execute() throws Exception { - // Nothing here; test method will run + try { + invocation.proceed(); + } catch (Throwable e) { + testException[0] = e; + } } + @Override public Invoker.InvocationContext getInvocationContext() { - return new Invoker.InvocationContext(invocationType); + return ctx; } }); + + if (testException[0] != null) { + throw testException[0]; + } + } else { + invocation.proceed(); } } From d669ef49d7057c543c9d345871405275fdfeb158 Mon Sep 17 00:00:00 2001 From: Alexandre Chatiron Date: Sun, 8 Mar 2026 15:47:12 +0100 Subject: [PATCH 2/3] fix(PlayJUnitExtension): use play current classLoader to run test --- .../src/play/test/PlayJUnitExtension.java | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/framework/src/play/test/PlayJUnitExtension.java b/framework/src/play/test/PlayJUnitExtension.java index 1290bfba1e..c1069bf413 100644 --- a/framework/src/play/test/PlayJUnitExtension.java +++ b/framework/src/play/test/PlayJUnitExtension.java @@ -56,25 +56,35 @@ public void interceptTestMethod(Invocation invocation, ReflectiveInvocatio // Run the test method within the Play thread context Invoker.InvocationContext ctx = new Invoker.InvocationContext(invocationType); Throwable[] testException = new Throwable[1]; - - Invoker.invokeInThread(new DirectInvocation() { - @Override - public void execute() throws Exception { - try { - invocation.proceed(); - } catch (Throwable e) { - testException[0] = e; + + // Set the Play classloader for this thread + ClassLoader originalLoader = Thread.currentThread().getContextClassLoader(); + if (Play.classloader != null) { + Thread.currentThread().setContextClassLoader(Play.classloader); + } + try { + Invoker.invokeInThread(new DirectInvocation() { + @Override + public void execute() throws Exception { + try { + invocation.proceed(); + } catch (Throwable e) { + testException[0] = e; + } } + + @Override + public Invoker.InvocationContext getInvocationContext() { + return ctx; + } + }); + + if (testException[0] != null) { + throw testException[0]; } - - @Override - public Invoker.InvocationContext getInvocationContext() { - return ctx; - } - }); - - if (testException[0] != null) { - throw testException[0]; + } finally { + // Restore original classloader + Thread.currentThread().setContextClassLoader(originalLoader); } } else { invocation.proceed(); From 33a5b554c3bdb674f7d21fe6454009f8bf619c04 Mon Sep 17 00:00:00 2001 From: Alexandre Chatiron Date: Sat, 14 Mar 2026 14:15:55 +0100 Subject: [PATCH 3/3] fix(PlayJUnitExtension): add afterEach method (#1556) --- .../src/play/test/PlayJUnitExtension.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/framework/src/play/test/PlayJUnitExtension.java b/framework/src/play/test/PlayJUnitExtension.java index c1069bf413..d1cef4972e 100644 --- a/framework/src/play/test/PlayJUnitExtension.java +++ b/framework/src/play/test/PlayJUnitExtension.java @@ -2,24 +2,19 @@ import java.io.File; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.junit.jupiter.api.extension.BeforeAllCallback; -import org.junit.jupiter.api.extension.BeforeEachCallback; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.InvocationInterceptor; -import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; -import org.junit.jupiter.api.extension.ReflectiveInvocationContext; +import org.junit.jupiter.api.extension.*; import play.Invoker; import play.Invoker.DirectInvocation; import play.Play; import java.lang.reflect.Method; -public class PlayJUnitExtension implements BeforeAllCallback, BeforeEachCallback, InvocationInterceptor, TestExecutionExceptionHandler { +public class PlayJUnitExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback, InvocationInterceptor, TestExecutionExceptionHandler { public static final String invocationType = "JUnitTest"; public static boolean useCustomRunner = false; - private static final ThreadLocal invocationContext = ThreadLocal.withInitial(() -> null); + private static final ThreadLocal invocationContext = new ThreadLocal<>(); @Override public void beforeAll(ExtensionContext context) throws Exception { @@ -50,6 +45,13 @@ public void beforeEach(ExtensionContext context) throws Exception { } } + @Override + public void afterEach(ExtensionContext context) throws Exception { + if (useCustomRunner) { + invocationContext.remove(); + } + } + @Override public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { if (useCustomRunner) {