Unit testing and declarative transactions with Spring and Hibernate

I’ve developed a simple service for creating users in an application, which I want to unit test. The service’s methods are declared as transactional with Spring metadata (In my case, I’m using annotations).

public class UserServiceImp implements UserService {
  public void createUser(User u) {

When unit testing, I don’t want to get the service through Spring… I want to test the real class, so I create it. This means that Spring doesn’t have a chance for adding the instrumentation (a proxy in my case) to the service class.

The result is that I get one transaction for each of the HibernateTemplate invocations performed inside the testing methods and service implementation, and the transaction is always rolled back (nothing is persisted to the database). In case you wondered, that’s a bad thing… for example, if I want to test that user creation correcly detects attempts to duplicate a user, I need to add a user and assert that a second attempt fails.

Update: I’ve written a new post about a better way for testing this scenario.

The solution is to use a TransactionTemplate and include all the test code inside its doInTransaction method.

I find it useful (albeit noisy) to throw a RuntimeException as the last thing inside the transaction, forcing a rollback. This way I’m assured that my test database is never modified and tests are repeatable. Just pay attention to the excepciont thrown and catch it to avoid signaling a test failure.

public void testSomething() throws Exception {
  TransactionCallback transac = new TransactionCallbackWithoutResult() {
    protected void doInTransactionWithoutResult(
      org.springframework.transaction.TransactionStatus status) {
      throw new RuntimeException("Rollback forced");
  PlatformTransactionManager ptm =
    (PlatformTransactionManager) ctx.getBean("txManager");
  try {
    new TransactionTemplate(ptm).execute(transac);
  } catch (RuntimeException e) {
    if (e.getMessage().equals("Rollback forced")) {
      /* Swallow exception. */
    } else {
      throw e;

I’m aware that there are some things I should not be doing… specially accessing the Spring context from my unit test (I keep a different configuration file for those, though), but I’m not sure about the implications of doing it this way… it just looked as the easier and quicker path.

How is the rest of the world testing this? I’ve read about using mock objects to avoid hitting the database, but I haven’t seen anything which can work with the Spring+Hibernate combo out of the box.

Any suggestions?

  • My profile

    View Abel Muño's profile on LinkedIn

    amuino on Twitter

  • My projects

    The cloud market:
    Find the virtual image you need on the cloud.
  • Top Posts

  • Archives

  • Categories


Get every new post delivered to your Inbox.

%d bloggers like this: