From 934394eb2a22f140f7ea2e967bb9dfb6e7a9b412 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:24:58 +0100 Subject: [PATCH] =?UTF-8?q?Document=20AOT=20workaround=20for=20@=E2=81=A0P?= =?UTF-8?q?ersistenceContext=20&=20@=E2=81=A0PersistenceUnit=20in=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although @⁠PersistenceContext and @⁠PersistenceUnit are still not supported in tests running in AOT mode, as of Spring Framework 7.0, developers can inject an EntityManager or EntityManagerFactory into tests using @⁠Autowired instead of @⁠PersistenceContext and @⁠PersistenceUnit, respectively. See commit 096303c477 See gh-33414 Closes gh-31442 --- .../ROOT/pages/testing/testcontext-framework/aot.adoc | 10 ++++++++++ .../test/context/aot/AotIntegrationTests.java | 4 +++- .../transaction/ejb/AbstractEjbTxDaoTestNGTests.java | 4 ++-- .../context/transaction/ejb/AbstractEjbTxDaoTests.java | 10 ++++++++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/aot.adoc b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/aot.adoc index 5348b383c4c..df049c3eb6e 100644 --- a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/aot.adoc +++ b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/aot.adoc @@ -43,6 +43,16 @@ alternative, you can set the same property via the xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism. ==== +[TIP] +==== +JPA's `@PersistenceContext` and `@PersistenceUnit` annotations cannot be used to perform +dependency injection within test classes in AOT mode. + +However, as of Spring Framework 7.0, you can inject an `EntityManager` or +`EntityManagerFactory` into tests using `@Autowired` instead of `@PersistenceContext` and +`@PersistenceUnit`, respectively. +==== + [NOTE] ==== The `@ContextHierarchy` annotation is not supported in AOT mode. diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java index 81634d5bdc6..12ed8565404 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/AotIntegrationTests.java @@ -147,7 +147,9 @@ class AotIntegrationTests extends AbstractAotTests { // We only include test classes named *Tests so that we don't pick up // internal TestCase classes that aren't really tests. .filter(clazz -> clazz.getSimpleName().endsWith("Tests")) - // TestNG EJB tests use @PersistenceContext which is not yet supported in tests in AOT mode. + // TestNG EJB tests use @EJB which is not supported in tests in AOT mode, and + // since @DisabledInAotMode is not able to disable TestNG tests at runtime, + // we have to filter out those tests here. .filter(clazz -> !clazz.getPackageName().contains("testng.transaction.ejb")) // AOT processing works for ParameterizedDependencyInjectionTests by itself // but fails for an unknown reason within the entire spring-test module. diff --git a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/AbstractEjbTxDaoTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/AbstractEjbTxDaoTestNGTests.java index fe4d4d82f61..1e8209de07d 100644 --- a/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/AbstractEjbTxDaoTestNGTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/testng/transaction/ejb/AbstractEjbTxDaoTestNGTests.java @@ -18,10 +18,10 @@ package org.springframework.test.context.testng.transaction.ejb; import jakarta.ejb.EJB; import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests; @@ -45,7 +45,7 @@ abstract class AbstractEjbTxDaoTestNGTests extends AbstractTransactionalTestNGSp @EJB protected TestEntityDao dao; - @PersistenceContext + @Autowired protected EntityManager em; diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/AbstractEjbTxDaoTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/AbstractEjbTxDaoTests.java index 7739f606e19..e1a3b9b263d 100644 --- a/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/AbstractEjbTxDaoTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/transaction/ejb/AbstractEjbTxDaoTests.java @@ -18,12 +18,13 @@ package org.springframework.test.context.transaction.ejb; import jakarta.ejb.EJB; import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; +import jakarta.persistence.EntityManagerFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @@ -51,9 +52,14 @@ abstract class AbstractEjbTxDaoTests { @EJB protected TestEntityDao dao; - @PersistenceContext + @Autowired protected EntityManager em; + // The EntityManagerFactory is not actually used by tests. We only declare it + // to ensure that dependency injection works for it. + @Autowired + protected EntityManagerFactory emf; + @Test void test1InitialState() {