mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-23 06:29:10 +00:00
Introduce tests for "No transaction in progress for @Nested test class"
Since we now officially support the TEST_METHOD ExtensionContextScope (see gh-35676 and gh-35680), this commit introduces tests which demonstrate that the issue raised in gh-34576 is no longer an "issue" if the user indirectly configures the SpringExtension to use the TEST_METHOD scope via the "junit.jupiter.extensions.testinstantiation.extensioncontextscope.default" configuration parameter.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-52
@@ -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 <a href="https://github.com/spring-projects/spring-framework/issues/28228">issue gh-28228</a>
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+98
@@ -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 <a href="https://github.com/spring-projects/spring-framework/issues/34576">issue gh-34576</a>
|
||||
*/
|
||||
@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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -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<Person> findAll() {
|
||||
return this.entityManager.createQuery("from Person", Person.class).getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Person findById(Long id) {
|
||||
return this.entityManager.find(Person.class, id);
|
||||
|
||||
+4
@@ -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<Person> findAll();
|
||||
|
||||
Person findById(Long id);
|
||||
|
||||
Person findByName(String name);
|
||||
|
||||
Reference in New Issue
Block a user