Visitar URL original
@Transactional test does not execute all JPA lifecycle callback methods · Issue #28228 · spring-projects/spring-framework · GitHub
Skip to content

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

Closed

Description

@hughwphamill

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.

Activity

  1. changed the title [-]@Transactional @SpringBootTest does not execute several entity listener methods[/-] [+]@Transactional test does not execute several entity listener methods[/+] on Mar 24, 2022
  2. added
    in: dataIssues in data modules (jdbc, orm, oxm, tx)
    in: testIssues in the test module
    on Mar 25, 2022
  3. self-assigned this
    on Mar 25, 2022
  4. changed the title [-]@Transactional test does not execute several entity listener methods[/-] [+]@Transactional test does not execute all JPA EntityListener methods[/+] on Mar 25, 2022
  5. changed the title [-]@Transactional test does not execute all JPA EntityListener methods[/-] [+]@Transactional test does not execute all JPA lifecycle callback methods[/+] on Mar 25, 2022
  6. sbrannen commented on Mar 25, 2022

    @sbrannen
    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.

  7. added this to the 5.3.18 milestone on Mar 25, 2022
  8. added a commit that references this issue on Mar 27, 2022
  9. hughwphamill commented on Mar 28, 2022

    @hughwphamill
    Author

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

  10. sbrannen commented on Mar 28, 2022

    @sbrannen
    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

Metadata

Metadata

Assignees

Labels

in: dataIssues in data modules (jdbc, orm, oxm, tx)in: testIssues in the test moduletype: documentationA documentation task

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions