-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Overview
In a Spring Boot project, with a test such as this:
@DataJpaTest
class PersonRepositoryTest {
@Autowired
PersonRepository personRepository;
@Autowired
TestEntityManager em;
@BeforeEach
void setup() {
em.persistAndFlush(new Person());
}
@Test
void shouldFindAllPersons() {
Iterable<Person> result = personRepository.findAll();
assertThat(result).hasSizeGreaterThanOrEqualTo(1);
}
@Nested
@TestPropertySource(properties = "spring.config.additional-location=optional:file:data.yaml")
class FindAll {
@Test
void shouldFindAllPersons() {
Iterable<Person> result = personRepository.findAll();
assertThat(result).hasSizeGreaterThanOrEqualTo(1);
}
}
}The test in the @Nested class fails with:
jakarta.persistence.TransactionRequiredException: no transaction is in progress
The test in the outer class works fine.
Removing the @TestPropertySource results in all tests passing, however in the test I'm actually working on, I need that to work around another bug. I assume that there are other scenarios which might cause this issue as well. I've spent some time debugging this, and it appears that 2 LocalContainerEntityManagerFactoryBeans are created - the transaction is started with one of them, but the code in the @BeforeEach is executed using the other. This results in the TransactionSynchronisationManager not finding the EntityManagerHolder in doGetResource().
The issue is present in 3.2.3, 3.2.12 and 3.4.3, and presumably everything in-between.
The root cause of the issue appears to be that an application context is created for the outer class, and the TestEntityManager is injected from that one, but then another application context is created for the inner class (which makes sense, since the configuration is different), and the transaction is started with the entity manager from the inner class' application context. However, the TestEntityManager has been injected from the outer class' application context, and any operations done using it do not have a transaction in progress.
I initially raised this issue against Spring Boot (spring-projects/spring-boot#44679), but after more investigation, it appears to be an issue with spring-test (present in version 6.2.3).