diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideTestExecutionListener.java
index 7237b8cfbaf..229fdb21553 100644
--- a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideTestExecutionListener.java
+++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideTestExecutionListener.java
@@ -95,7 +95,7 @@ public class BeanOverrideTestExecutionListener extends AbstractTestExecutionList
private static void injectFields(TestContext testContext) {
Object testInstance = testContext.getTestInstance();
// Since JUnit Jupiter 5.12, if the SpringExtension is used with Jupiter's
- // ExtensionContextScope.TEST_METHOD mode, the value returned from
+ // TEST_METHOD ExtensionContextScope, the value returned from
// testContext.getTestClass() may refer to the declaring class of the test
// method which is about to be invoked (which may be in a @Nested class
// within the class for the test instance). Thus, we use the class for the
@@ -109,7 +109,7 @@ public class BeanOverrideTestExecutionListener extends AbstractTestExecutionList
Assert.state(applicationContext.containsBean(BeanOverrideRegistry.BEAN_NAME), () -> """
Test class %s declares @BeanOverride fields %s, but no BeanOverrideHandler has been registered. \
If you are using @ContextHierarchy, ensure that context names for bean overrides match \
- configured @ContextConfiguration names.""".formatted(testContext.getTestClass().getSimpleName(),
+ configured @ContextConfiguration names.""".formatted(testClass.getSimpleName(),
handlers.stream().map(BeanOverrideHandler::getField).filter(Objects::nonNull)
.map(Field::getName).toList()));
BeanOverrideRegistry beanOverrideRegistry = applicationContext.getBean(BeanOverrideRegistry.BEAN_NAME,
diff --git a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaConfig.java b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaConfig.java
new file mode 100644
index 00000000000..ca98ba2e3e4
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaConfig.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.test.context.orm.jpa;
+
+import javax.sql.DataSource;
+
+import jakarta.persistence.EntityManagerFactory;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.Database;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.test.context.orm.jpa.domain.JpaPersonRepository;
+import org.springframework.test.context.orm.jpa.domain.Person;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@Configuration(proxyBeanMethods = false)
+@EnableTransactionManagement
+class JpaConfig {
+
+ @Bean
+ JpaPersonRepository personRepository() {
+ return new JpaPersonRepository();
+ }
+
+ @Bean
+ EmbeddedDatabase dataSource() {
+ return new EmbeddedDatabaseBuilder().generateUniqueName(true).build();
+ }
+
+ @Bean
+ JdbcTemplate jdbcTemplate(DataSource dataSource) {
+ return new JdbcTemplate(dataSource);
+ }
+
+ @Bean
+ LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
+ LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
+ emfb.setDataSource(dataSource);
+ emfb.setPackagesToScan(Person.class.getPackage().getName());
+ HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
+ hibernateJpaVendorAdapter.setGenerateDdl(true);
+ hibernateJpaVendorAdapter.setDatabase(Database.H2);
+ emfb.setJpaVendorAdapter(hibernateJpaVendorAdapter);
+ return emfb;
+ }
+
+ @Bean
+ JpaTransactionManager transactionManager(EntityManagerFactory emf) {
+ return new JpaTransactionManager(emf);
+ }
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaEntityListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaEntityListenerTests.java
index d9b9bb8768d..5f1267c15d1 100644
--- a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaEntityListenerTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaEntityListenerTests.java
@@ -18,30 +18,18 @@ package org.springframework.test.context.orm.jpa;
import java.util.List;
-import javax.sql.DataSource;
-
import jakarta.persistence.EntityManager;
-import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.PersistenceContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
-import org.springframework.orm.jpa.JpaTransactionManager;
-import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
-import org.springframework.orm.jpa.vendor.Database;
-import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
-import org.springframework.test.context.orm.jpa.domain.JpaPersonRepository;
import org.springframework.test.context.orm.jpa.domain.Person;
import org.springframework.test.context.orm.jpa.domain.PersonListener;
import org.springframework.test.context.orm.jpa.domain.PersonRepository;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import static org.assertj.core.api.Assertions.assertThat;
@@ -55,7 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @see issue gh-28228
* @see org.springframework.test.context.orm.hibernate.HibernateSessionFlushingTests
*/
-@SpringJUnitConfig
+@SpringJUnitConfig(JpaConfig.class)
@Transactional
@Sql(statements = "insert into person(id, name) values(0, 'Jane')")
class JpaEntityListenerTests {
@@ -156,43 +144,4 @@ class JpaEntityListenerTests {
}
}
-
- @Configuration(proxyBeanMethods = false)
- @EnableTransactionManagement
- static class Config {
-
- @Bean
- PersonRepository personRepository() {
- return new JpaPersonRepository();
- }
-
- @Bean
- DataSource dataSource() {
- return new EmbeddedDatabaseBuilder().generateUniqueName(true).build();
- }
-
- @Bean
- JdbcTemplate jdbcTemplate(DataSource dataSource) {
- return new JdbcTemplate(dataSource);
- }
-
- @Bean
- LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
- LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
- emfb.setDataSource(dataSource);
- emfb.setPackagesToScan(Person.class.getPackage().getName());
- HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
- hibernateJpaVendorAdapter.setGenerateDdl(true);
- hibernateJpaVendorAdapter.setDatabase(Database.HSQL);
- emfb.setJpaVendorAdapter(hibernateJpaVendorAdapter);
- return emfb;
- }
-
- @Bean
- JpaTransactionManager transactionManager(EntityManagerFactory emf) {
- return new JpaTransactionManager(emf);
- }
-
- }
-
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaPersonRepositoryTests.java b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaPersonRepositoryTests.java
new file mode 100644
index 00000000000..9811a848d55
--- /dev/null
+++ b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaPersonRepositoryTests.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2002-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.test.context.orm.jpa;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
+import org.junit.platform.suite.api.ConfigurationParameter;
+import org.junit.platform.suite.api.SelectClasses;
+import org.junit.platform.suite.api.Suite;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+import org.springframework.test.context.orm.jpa.domain.Person;
+import org.springframework.test.context.orm.jpa.domain.PersonRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Test {@link Suite @Suite} which selects a single test class and runs it with
+ * {@link ExtensionContextScope#TEST_METHOD}.
+ *
+ * @author Sam Brannen
+ * @since 6.2.13
+ * @see issue gh-34576
+ */
+@Suite
+@SelectClasses(JpaPersonRepositoryTests.TestCase.class)
+@ConfigurationParameter(
+ key = ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME,
+ value = "test_method" // If this is changed to "default", NestedTests will fail.
+)
+// Even though this is a @Suite, it is intentionally named JpaPersonRepositoryTests
+// instead of JpaPersonRepositoryTestSuite, so that it is run with the Gradle build
+// due to the "*Tests" naming convention.
+class JpaPersonRepositoryTests {
+
+ /**
+ * Transactional tests for JPA support with {@link Nested @Nested} test classes.
+ */
+ @SpringJUnitConfig(JpaConfig.class)
+ @Transactional
+ @Sql(statements = "insert into person(id, name) values(0, 'Jane')")
+ static class TestCase {
+
+ @PersistenceContext
+ EntityManager em;
+
+ @Autowired
+ PersonRepository repo;
+
+
+ @BeforeEach
+ void setup() {
+ em.persist(new Person("John"));
+ em.flush();
+ }
+
+ @Test
+ void findAll() {
+ assertThat(repo.findAll()).map(Person::getName).containsExactlyInAnyOrder("Jane", "John");
+ }
+
+
+ @Nested
+ // Declare a random test property to ensure we get a different ApplicationContext.
+ @TestPropertySource(properties = "nested = true")
+ class NestedTests {
+
+ @Test
+ void findAll() {
+ assertThat(repo.findAll()).map(Person::getName).containsExactlyInAnyOrder("Jane", "John");
+ }
+ }
+
+ }
+
+}
diff --git a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/JpaPersonRepository.java b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/JpaPersonRepository.java
index cd4bf0d7379..2218279566f 100644
--- a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/JpaPersonRepository.java
+++ b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/JpaPersonRepository.java
@@ -16,6 +16,8 @@
package org.springframework.test.context.orm.jpa.domain;
+import java.util.List;
+
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
@@ -35,6 +37,12 @@ public class JpaPersonRepository implements PersonRepository {
@PersistenceContext
private EntityManager entityManager;
+
+ @Override
+ public List findAll() {
+ return this.entityManager.createQuery("from Person", Person.class).getResultList();
+ }
+
@Override
public Person findById(Long id) {
return this.entityManager.find(Person.class, id);
diff --git a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/PersonRepository.java b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/PersonRepository.java
index 111e966b249..6bb3f11ca32 100644
--- a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/PersonRepository.java
+++ b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/domain/PersonRepository.java
@@ -16,6 +16,8 @@
package org.springframework.test.context.orm.jpa.domain;
+import java.util.List;
+
/**
* Person repository API.
*
@@ -24,6 +26,8 @@ package org.springframework.test.context.orm.jpa.domain;
*/
public interface PersonRepository {
+ List findAll();
+
Person findById(Long id);
Person findByName(String name);