I would like to write tests about revision. In the console I see the update call of Hibernate, BUT no insertions into AUD-Table.
Test-Method:
@DataJpaTest
class JPAHistoryTest {
@Test
public void test() {
def entity = // create Entity
def entity2 = // create same Entity
entity2.setPrice(entity2.getPrice() + 10)
entity2.setLastUpdate(entity2.lastUpdate.plusSeconds(10))
service.save(entity)
service.save(entity2)
repository.flush() // Hibernate updates changes
assert repository.findRevisions(entity.id).content.empty == false // FAIL!
}
}
My Entity looks like:
@Entity
@Audited
class Entity {
@Id @GeneratedValue Long id
@Column(nullable = false) BigDecimal price
}
Thank you very much.
The Envers module is a core Hibernate model that works both with Hibernate and JPA. In fact, you can use Envers anywhere Hibernate works whether that is standalone, inside WildFly or JBoss AS, Spring, Grails, etc. The Envers module aims to provide an easy auditing / versioning solution for entity classes.
Additionaly, there is a "REVINFO" table generated, which contains only two fields: the revision id and revision timestamp. A row is inserted into this table on each new revision, that is, on each commit of a transaction, which changes audited data.
Note that if Hotel was audited RelationTargetAuditMode.NOT_AUDITED will just be ignored (you will have historical data for Hotel). @ NotAudited means "I just don't care for this field in historical data" (it won't be saved, relationship will be null, you won't see it when looking historical data about CustomerBooking )
As I found out I keep the @DataJpaTest
and add @Transactional(propagation = NOT_SUPPORTED)
to make sure, the test methods will not start a transaction. Because if they would run in a transaction, then the envers history entries will be written, when the test close the transaction.
@RunWith(SpringRunner)
@DataJpaTest
@Transactional(propagation = NOT_SUPPORTED)
class JPAHistoryTest {
@After
void after() {
repository.deleteAll()
}
@Test
public void testTwoInsert() {
def entity1 = // ...
def entity2 = // ...
sut.save(entity1 )
sut.save(entity2 )
assert repository.findRevisions(entity1.id).content.size() == 1
assert repository.findRevisions(entity2.id).content.size() == 1
}
}
I found same problem as you and tried @michael-hegner answer, but I used TestEntityManager
class so I can't get EntityManager
when there is no transaction (propagation
set to NOT_SUPPORTED
).
In my case the solution was to manually commit transaction from TestEntityManager
, to first save entity and changes and next query for revisions.
Here's a test class:
@DataJpaTest
class UserRepositoryTest {
@Autowired
private TestEntityManager testEntityManager;
@Test
public void shouldBeAudited() {
User user = getTestUser();
testEntityManager.persistAndFlush(user);
user.setPassword("tset");
testEntityManager.merge(user);
// This line is critical here to commit transaction and trigger audit logs
testEntityManager.getEntityManager().getTransaction().commit();
// With propagation = NOT_SUPPORTED this doesn't work: testEntityManager.getEntityManager()
AuditReader auditReader = AuditReaderFactory.get(testEntityManager.getEntityManager());
List revisions = auditReader.createQuery()
.forRevisionsOfEntity(User.class, true)
.add(AuditEntity.id().eq(user.getId()))
.getResultList();
assertEquals(1, revisions.size());
}
private User getTestUser() {
User user = new User();
user.setUsername("test");
user.setEmail("test");
user.setPassword("test");
return user;
}
}
It could be mandatory to manually remove user after Test because transaction was commited and in other tests it may causes some problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With