I have a server application which interacts with a database via JPA. Methods in this application usually look like this:
entityManager.getTransaction().begin();
try {
// do some work
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();
}
I need to write tests for each of these methods. I would like to be able to undo any changes made in the tested method so the database is in the same state at the start of every test.
My first thought was to do this in my test method:
entityManager.getTransaction().begin();
myMethod();
entityManager.getTransaction().rollback();
but that causes java.lang.IllegalStateException: Transaction already active
when the tested method calls begin()
.
So then I commented out the begin()
line of the tested method. Then I get org.hibernate.TransactionException: Cannot rollback transaction in current status [COMMITTED]
on the line where I rollback the transaction after the tested method call.
So I removed the commit()
from the tested method. This makes the test work, but when the actual application runs this method, the changes don’t persist. In addition, the id field of my entity is not set after entityManager.persist(myEntity)
, which is important for creating entities which reference other entities.
I tried using the @Transactional
annotation in several places including on the test class, the test method, and the tested method (and every permutation of those I could think of). It would get the test to work, but not the application.
I know I could manually undo the changes I expect to see after the tested method is called, but this would be not only tedious but error prone and brittle as the tested method could change to modify other data in the database and the test method might not be updated.
My application uses javaee-api 8.0.1, and the persistence provider is hibernate.