views:

54

answers:

1

I would like to be able to verify if each unit of work is done in its own transaction, or as part of a single global transaction.

I have a method (defined using spring and hibernate), which is of the form:

private void updateUser() {
    updateSomething();
    updateSomethingElse();
}

This is called from two places, the website when a user logs in and a batch job which runs daily. For the web server context, it will run with a transaction created by the web server. For the batch job, it must have one transaction for each user, so that if something fails during this method, the transaction is rolled back. So we have two methods:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void updateUserCreateNewTransaction() {
    updateUser();
}

@Transactional(propagation=Propagation.REQUIRED)
public void updateUserWithExistingTransaction() {
    updateUser();
}

updateUserCreateNewTransaction() is called from the batch job, and updateUserWithExistingTransaction() from the web server context.

This works. However, it is very important that this behaviour (of the batch) not be changed, so I wish to create a test that tests this behaviour. If possible, I would like to do this without changing the code.

So some of the options open to me are:

  1. Count the transactions opened in the database during the run of the batch job.

  2. Change the data in some sublte way so that at least one user update fails, in the updateSomethingElse() method, and check that the updateSomething() for that user has not taken place.

  3. Code review.

1 is a very database dependent method, and how do I guarantee that hibernate won't create a transaction anyway?. 2 seems better, but is very complex to set up. 3 is not really practical because we will need to do one for every release.

So, does anyone have a method which would enable me to test this situation?

Thanks.

+2  A: 

I would try to setup a test in a unit test harness using an in memory HSQLDB and EasyMock (or some other mocking framework).

You could then have the updateSomething() method really write to the HSQL database but use the mock framework to mock the updateSomethingElse() method and throw a RuntimeException from that method. When that is done you could perform a query against the HSQLDB to verify that the updateSomething() stuff was rolled back.

It will require some plumbing to setup the HSQLDB and transaction manager but when that is done you have a test without external dependencies that can be re-run whenever you like.

Kristoffer E