0

I have a integration test where I am testing some business logic methods that run between two of my domain objects.

Because I have multiple test that create the same set of objects to run my tests under different conditions, I create the domain objects in the setup and delete them in the cleanup.

However I am getting an org.springframework.dao.DuplicateKeyException the second time I try to save this object, where the only change I made to the object was not a uniqued field. It seems like the version from the prior test may be hanging around somehow based on the messages below.

If I do not use the setup and cleanup but instead create all the objects in the body of each test method, the tests pass.

Relevant code and error follows:

import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*
import com.grapevine.negotiator2.DomainFactory
@Integration
@Rollback
class AgentSpec extends Specification {
  User u
  Agent a
  Buyer b
  User u2

  def setup() {

    //make two users
    u2 = DomainFactory.makeUser("Pancho", "password", E.SpringAuthority.ROLE_USER)
    u =DomainFactory.makeUser("Gorman","password",E.SpringAuthority.ROLE_USER)
    //make a buyer
    b = DomainFactory.makeBuyer("Sam Jones")
    b.scaleFear = 0.0
    b.scaleGreed = 0.0
    b.save()
    //make an agent
     a = DomainFactory.makeAgent(u)
}

def cleanup() {
    DomainFactory.killUser(u)
    DomainFactory.killUser(u2)
    b.delete(flush: true)
    a.delete(flush:true)
}
void "TestforBadReputation"() {
    given:  "An agent with bad reputation"
    a.reputation=-5.1
    expect: "An agent with a <-5 reputation to be rejected by any buyer"
    a.validate()
    a.save()
    b.respondToRepresentationRequest(a)==E.BuyerAgencyResponse.BadReputation

}
void "TestforAlreadyHasAgent"() {
    given: "An buyer who already has an agent"
    b.agent = a
    b.save()
    a.reputation=5     
    expect: "Buyer rejects agency request"
    a.validate()
    a.save()
    b.respondToRepresentationRequest(a)== E.BuyerAgencyResponse.AlreadyRepresented
}
}

Error:

org.springframework.dao.DuplicateKeyException: A different object with the same 
identifier value was already associated with the session : [com.grapevine.negotiator2.Agent#13]; 
nested exception is org.hibernate.NonUniqueObjectException: A different object 
with the same identifier value was already associated with the session : [com.grapevine.negotiator2.Agent#13]

at org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:259)
at org.grails.orm.hibernate.GrailsHibernateTemplate.convertHibernateAccessException(GrailsHibernateTemplate.java:661)
at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:247)
at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:187)
at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:110)
at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.performSave(AbstractHibernateGormInstanceApi.groovy:241)
at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.save(AbstractHibernateGormInstanceApi.groovy:158)
at org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:116)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:98)
at com.grapevine.negotiator2.AgentSpec.$tt__$spock_feature_0_4(AgentSpec.groovy:98)
at com.grapevine.negotiator2.AgentSpec.TestforBuyerAcceptance2_closure7(AgentSpec.groovy)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:430)
at grails.transaction.GrailsTransactionTemplate$1.doInTransaction(GrailsTransactionTemplate.groovy:70)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.transaction.GrailsTransactionTemplate.executeAndRollback(GrailsTransactionTemplate.groovy:67)
at com.grapevine.negotiator2.AgentSpec.TestforBuyerAcceptance2(AgentSpec.groovy)

Caused by: org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.grapevine.negotiator2.Agent#13] at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:642) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:227) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73) at org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.onSaveOrUpdate(ClosureEventTriggeringInterceptor.java:81) at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:651) at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:643) at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:638) at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.performSave_closure3(AbstractHibernateGormInstanceApi.groovy:242) at groovy.lang.Closure.call(Closure.java:414) at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:243) ... 14 more

GGizmos
  • 3,443
  • 4
  • 27
  • 72
  • Is info in here of any use? http://stackoverflow.com/questions/33829465/grails-3-0-9-spock-integration-tests-rollback-annotation-is-not-working – Mike W Dec 07 '16 at 07:59
  • Is it possible your `delete` calls are failing silently for some reason? Maybe add `failOnError: true` just to make sure. Also, in the cleanup method, what happens if you try and fetch the delete items? Do you get back 0 results? – Gregg Dec 07 '16 at 17:02
  • Cant really find anything that seems applicable to this problem in the post. I took the easy way out and moved everything out of the setup() into the test methods themselves. – GGizmos Dec 10 '16 at 20:05
  • PS. failOnError:true doesn't fail. trying to fetch the deleted item in the cleanup shows the item deleted. – GGizmos Dec 10 '16 at 21:43

0 Answers0