Skip to content

TestEntityManager can't be configured in @BeforeAll method in test class with @TestInstance(PER_CLASS) in JUnit Jupiter [SPR-16550] #21093

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spring-projects-issues opened this issue Mar 4, 2018 · 15 comments
Assignees
Labels
in: test Issues in the test module status: duplicate A duplicate of another issue

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Mar 4, 2018

Aleksandr opened SPR-16550 and commented

When trying to autowire Spring Boot's TestEntityManager in method annotated as @BeforeAll, the following exception is thrown:

java.lang.IllegalStateException: No transactional EntityManager found

Other beans are autowired into this method without problems.

The case is following - since I have one test class instance for all tests in it, and they require the same prepopulated DB, why not fill the DB once after test class instantiation?

Sample project is referenced in the issue.


Reference URL: https://gitlab.com/AleksandrSl/spring-sandbox/blob/junit-5-security/src/test/kotlin/pro/parseq/springsandbox/entities/UserItemsSecurityTests.kt

Issue Links:

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

I'm afraid TestEntityManager is a Spring Boot specific feature: Please report it to the Spring Boot project at https://github.com/spring-projects/spring-boot/issues instead.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

With respect to the exception above, this simply means that a persistence operation was triggered without a transaction being active for the current thread. You should be able to inject a TestEntityManager even in such an per-class callback but every operation called on it would lead to that exception, unless you're manually creating a transaction for those operations.

@spring-projects-issues
Copy link
Collaborator Author

Aleksandr commented

I thought that @Transactional is responsible for this, because in other test methods and @BeforeEach method transactions exist

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Just looked at your test code, I see where you're coming from here now: You expect all such @Before* to execute within a test-managed transaction, based on the class-level @Transactional marker.

Sam Brannen, what's your take on this? I suppose BeforeAll is simply not executing within the TransactionalTestExecutionListener? It this part of a well-defined lifecycle or potentially worth revisiting?

@spring-projects-issues
Copy link
Collaborator Author

Aleksandr commented

The weird thing, in my point of view, that @BeforeEach works in transactional context both with method and class level @Transactional annotations. But
@BeforeAll is not in context with both annotations, though with Lifecycle.PER_CLASS @BeforeAll method is not static and invoked after class instantiation.

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

The fact that a @BeforeAll method is not invoked within the test-managed transaction is by design.

The scope of a test-managed transaction is tied to the execution of a test method, test factory, or test template method invocation.

Thus it is not possible for Spring to manage a test-managed transaction at the container level (i.e., when @BeforeAll and @AfterAll methods are invoked).

@spring-projects-issues
Copy link
Collaborator Author

Aleksandr commented

So it's not possible to manage transactions in these methods at all, even in the Lifecycle.PER_CLASS @BeforeAll case?

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Mar 5, 2018

Sam Brannen commented

Juergen Hoeller,

It this part of a well-defined lifecycle or potentially worth revisiting?

It is part of a well-defined lifecycle; however, similar issues have been raised in the past for TestNG:

So we could potentially revisit #10191, but... I think the use case described in this issue is actually quite different.

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

Sl.aleksandr,

Is your goal to make changes to the database within a test-managed transaction that gets rolled back after the entire class?

Or is your goal to make changes to the database in an isolated, committed transaction before all test methods (which potentially have their own isolated, rolled-back transactions)?

@spring-projects-issues
Copy link
Collaborator Author

Sam Brannen commented

So it's not possible to manage transactions in these methods at all, even in the Lifecycle.PER_CLASS @BeforeAll case?

You can of course manage a transaction manually in such a method -- for example, via Spring's TransactionTemplate; you just cannot have such a method participate in a test-managed transaction that is created for you automatically.

@spring-projects-issues
Copy link
Collaborator Author

Aleksandr commented

Sam Brannen

Is your goal to make changes to the database within a test-managed transaction that gets rolled back after the entire class?
This is the case. Thanks for the references!

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Mar 9, 2018

Sam Brannen commented

OK.... then my earlier assumption about this being a different topic was wrong.

In light of that and the upcoming support for scenario tests in JUnit Jupiter (potentially in JUnit Jupiter 5.2), I think it would be prudent to reopen #10191.

Consequently, I will close this issue as a duplicate.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Mar 9, 2018

Sam Brannen commented

FYI: I have reopened #10191.

@Tockra
Copy link

Tockra commented Nov 8, 2021

Or is your goal to make changes to the database in an isolated, committed transaction before all test methods (which potentially have their own isolated, rolled-back transactions)?

I have the same issues and I'm trying to do exactly what you described above. I want to do a database setup before my tests and then test some stuff. But it don't work with the BeforeAll Method.

My Entity class:

@Entity
@Table(name = "myTable")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id", scope = CampaignEntity.class)
@EqualsAndHashCode
@ToString
@NoArgsConstructor
@Setter
@Getter
public class MyEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long id;
    
        @OneToMany(mappedBy = "someName", cascade = CascadeType.MERGE, orphanRemoval = true)
    private final Set<DifferentEntity> additionAttr = new HashSet<>();
}

My before All method:

   @BeforeAll
    void startUp() {
        var myEntities = TestDataGenerator.getListOfEntities(COUNT, ADDITIONAL_ATTR_COUNT);
        myRepo.saveAllAndFlush(myEntities); // When I set a debug point here the additionAttr is set with size ADDITIONAL_ATTR_COUNT
    }

My test, which fails at the assertion:

    @Test
    @Transactional
    void myFailingTest() throws Exception {
        final MyEntity myEntity = this.myRepo.findAll().get(0);
        assertThat(myEntity.getAdditionalAttr()).hasSize(ADDITIONAL_ATTR_COUNT); // here it fails because there is size 0 ...
    }

Is there a way to fix that issue. it should be possible to do a test setup for the database !?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

3 participants