Skip to content
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

@Transactional test does not execute all JPA lifecycle callback methods #28228

Closed
hughwphamill opened this issue Mar 24, 2022 · 3 comments
Closed
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) in: test Issues in the test module type: documentation A documentation task
Milestone

Comments

@hughwphamill
Copy link

hughwphamill commented Mar 24, 2022

Spring Boot v2.6.4

@Transactional tests are useful to roll back any test data created during tests; however, when a Spring integration test is annotated with @Transactional the following JPA lifecycle callback methods are not executed:

  • @PostPersist
  • @PostLoad
  • @PreUpdate
  • @PostUpdate

Example project with tests demonstrating the issue here:

https://github.com/hughwphamill/transaction-test-entity-issue

I understand this is the desired behavior from a JPA perspective, but it's still undesirable from a test perspective.

@Transactional is incredibly useful in Spring integration tests to roll back test data, while exercising your whole application end to end. If your business logic uses JPA entity listeners then your application can't be properly tested in a @Transactional test.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 24, 2022
@snicoll snicoll changed the title @Transactional @SpringBootTest does not execute several entity listener methods @Transactional test does not execute several entity listener methods Mar 24, 2022
@sbrannen sbrannen added in: data Issues in data modules (jdbc, orm, oxm, tx) in: test Issues in the test module labels Mar 25, 2022
@sbrannen sbrannen self-assigned this Mar 25, 2022
@sbrannen sbrannen changed the title @Transactional test does not execute several entity listener methods @Transactional test does not execute all JPA EntityListener methods Mar 25, 2022
@sbrannen sbrannen changed the title @Transactional test does not execute all JPA EntityListener methods @Transactional test does not execute all JPA lifecycle callback methods Mar 25, 2022
@sbrannen
Copy link
Member

Hi @hughwphamill,

Thanks for opening your first issue for the Spring Framework. 👍🏻

If your business logic uses JPA entity listeners then your application can't be properly tested in a @Transactional test.

You can still test the behavior of your JPA lifecycle callback methods with @Transactional test methods, but you need to take into account the semantics of the unit of work (first level cache) in your ORM tool (i.e., the "persistence context" in JPA terminology).

This usually means that you need to flush the state of the unit of work to the underlying database.

In the Avoid false positives when testing ORM code note in the Testing chapter of the reference manual, we point out that invoking entityManager.flush() will help you to achieve this with JPA.

For your particular test class, you can make the @PostPersist, @PreUpdate, and @PostUpdate tests pass by invoking entityManager.flush() after each invocation of repository.save(entity). To make the @PostLoad test pass, you additionally need to invoke entityManager.clear() after calling entityManager.flush().

In summary, the behavior you have encountered is to be expected since all interactions with the unit of work occur within the same transaction.

To ensure that your JPA lifecycle callback methods are invoked, you have two choices.

  1. Flush and clear the unit of work as described above within a @Transactional test.
  2. Do not use @Transactional tests.

I will add a note to the reference manual to point out the need to flush and clear when using JPA lifecycle callback methods, in case other developers encounter this issue.

@sbrannen sbrannen added type: documentation A documentation task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Mar 25, 2022
@sbrannen sbrannen added this to the 5.3.18 milestone Mar 25, 2022
sbrannen added a commit to sbrannen/spring-framework that referenced this issue Mar 27, 2022
sbrannen added a commit that referenced this issue Mar 27, 2022
@hughwphamill
Copy link
Author

@sbrannen Thanks very much for the detailed explanation and for updating the docs!

@sbrannen
Copy link
Member

@hughwphamill, you're welcome!

And thanks for providing feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) in: test Issues in the test module type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

3 participants