views:

105

answers:

1

How should I test a service method that is transactional for its simultaneous use (it updates a database row by decreasing a value)?

I have setup a JUnit test class with SpringJunit4ClassRunner and components are @autowired.

Just spawning threads which would call the method doesn't seem to work. I'm not sure whether this has something to do with the Spring proxy mechanism.

What I would like to achieve is to create a situation where simultaneously two threads are "inside" the tested method and other one will fail and rollback. e.g. The row value is 3 and both method calls try to decrease the value by 2; if the method wouldn't work, the value would be -1, which is illegal. But I want that either both of the calls fail and rollback, or failing the one that tries to update it an instant later than the other.

Is this even possible?

+3  A: 

The first problem is that the transaction context is bound to one thread (with a thread local). So you have to start a transaction in each of your threads. (I think there is no support for this in spring. You can start transaction programmatically with the transaction manager.)

The code you described: read, decrement, write does only work with the right isolation level (serialized and repeatable read would work).

After this setup is done, you can test the behavior by blocking one thread while he has the database lock. You can use a Latch for this.

The thread without database lock will now still not rollback. It will block until the database lock is available again. The scheme you're describing is quite similiar to Optimistic concurrency control so maybe this is already implemented.

Thomas Jung
This sounds pretty much what I wanted. I'll try to see if I get everything to work. Thank you!
egaga