Saturday, November 17, 2012

How to JUnit-test Envers

Recently, me and some fellow students of mine had to do a homework assignment with Spring and Hibernate. One of the requirements was to include versioning for some of the entities.
At first we thought about programming something on our own by using AOP and an interface. After suggesting this to our professor he told us, that there might be already a framework for versioning that works with Hibernate.
So I found Envers.
Using Envers isn't very difficult. If you want to know more about Envers, you'll have to take a look at its documentation.
My problem was how to write JUnit-Tests for the methods in my DAOs that use the AuditReader class.

Before I start explaining my problem and my solution I just want to tell you, that I'm no Spring developer and it was my first project with Spring (my teammates had no experience with Spring, too).

When persisting some objects in the tests Envers never wrote any data into its revision tables. I soon found out that the @Transactional annotation at my test-class put every method in one transaction (Spring people will know ;) ). At the end of one test-method the commit was performed and Envers didn't react.
So @Transactional had to vanish and the search began.

So when I tried to find a solution I found this article on Dzone but calling commit() on my session or using the TransactionManager lead to some exceptions.
This thread on stackoverflow finally was the solution. Unfortunately the second answer doesn't have any rating, so I ignored it and I had to visit that thread three times to recognize it. (please rate it up if you're registered on stackoverflow)

The superclass for all my Envers tests looks like this: ApplicationContextAwareTest
and in every test it use this method with the TransactionTemplate:
public <T> T makePersistentInTransaction(final T toPersist,
final GenericDAO<T, Long> dao) {
return transactionTemplate.execute(new TransactionCallback<T>() {
@Override
public T doInTransaction(TransactionStatus status) {
return dao.makePersistent(toPersist);
}
});
};

After every call there is a commit and Envers starts working. And after persisting some objects I can tests my methods, which take care of versioning.
Finally everything could be tested and I was happy :D 

Feel free to browse the GitHub project. It contains the whole homework. And please don't wonder that nearly everything is in German ;)

 

Copyright @ 2013 Wrong tracks of a developer.

Designed by Templateiy