So I am working with Grails. My application involves an object coming in, and being updated in the db and returned. It's this behavior I am trying to test in a Spock IntegrationSpec.
Essentially, my test looks like this (pseudo-code)
setUp
{
Session sess = sessionFactory.openSession();
Transaction tx = null;
try{
...
//These loaded fixtures include the shop
//that I want to update
fixtures = fixtureLoader.load(fixtureLocationsArray)
...
tx.commit()
...
sessionFactory.currentSession.flush()
sessionFactory.currentSession.clear()
}
void testUpdate()
{
Shop shop = fixtures.shop
shop.discard()
//Pure, unadulterated desperation below
sessionFactory.currentSession.flush()
sessionFactory.currentSession.clear()
sessionFactory.getCache().evictEntityRegion(Shop)
ShopDTO shopDto = convertToDTO(shop)
shopDto.name = "Updated Shop"
//Chokes while in the controller
returnedShopDTO = dtoController.update(shopDto)
}
I have tried everything, including wrapping my fixture creation in a transaction, evicting, discarding and doing whatever I can to make the session "forget" the object. No matter what I do, I always get an error like
org.hibernate.StaleObjectStateException:
Row was updated or deleted by another transaction
(or unsaved-value mapping was incorrect)
or it will complain that something with that id already exists in the session. From what I can tell, the entire test occurs in one fat daddy session. So when I go to "update" it inserts the fixture, and then calls "select last_row_id" or something. It then assigns the next id to my updated shop. So in the end, I get two inserts if it doesn't crash, the first from the fixture, the second from my save/merge call.
Any help on creating fixtures, and then making them disappear from the session/transaction/doo-hickey is greatly appreciated.
Turns out I had to disable versioning on my project. I did this by adding the following code to my domain class. I'm not sure if this is the correct solution, but it made the various errors go away.
static mapping = {
...
version false
...
}