John
John

Reputation: 11831

How to create Grails domain object but do not save?

I have a method that should create a domain object. However, if during the course of building the object a condition occurs, the method should just return and not save the object.

Given:

class SomeDomainObjectClass {
    String name
}

class DomCreatorService {
    def createDom() {
        SomeDomainObjectClass obj = new SomeDomainObjectClass(name: "name")

        // do some processing here and realise we don't want to save the object to the database
        if (!dontWannaSave) {
            obj.save(flush: true)
        }
    }
}

within my test (service is instance of DomCreatorService):

expect: "it doesn't exist at first" 
SomeDomainObjectClass.findByName("name") == null

when: "we attempt to create the object under conditions that mean it shouldn't be saved"
// assume that my test conditions will mean dontWannaSave == true and we shouldn't save     
service.createDom() 

then: "we shouldn't be able to find it and it shouldn't exist in the database"
// check that we still haven't created an instance
SomeDomainObjectClass.findByName("name") == null

My last line is failing. Why does the last findByName return true, i.e. why can my object be found? I thought it would only find objects saved to the database. What should I be testing for to see if my object has not been created?

Upvotes: 3

Views: 2223

Answers (1)

Burt Beckwith
Burt Beckwith

Reputation: 75671

You must be leaving something out - if you simply create an instance but don't call any GORM methods on it, Hibernate can't know about it. The only way it starts to manage the object is by you "attaching" it with that initial save() call. Without that, it's just like any other object.

What you will see, but which is not affecting you here, is what @agusluc describes. If you load a previously persisted instance and modify any property, at the end of the request Hibernate's dirty checking will kick in, detect that this attached but unsaved instance is dirty, and it will push the changes to the database, even if you don't call save(). In that scenario, if you don't want an edit to persist, detach the object from the session with a call to discard(). This has nothing to do with what you're seeing, because you haven't attached anything.

There could be an instance with that name property already. Check the other properties of what the findByName query returns and I assume you'll see that it's a previously persisted instance.

Also, is this a unit test or integration? Be sure to use integration tests for persistence - the unit test mocking is not for testing domain classes, it's only supposed to be used to give GORM behavior to domain classes when testing other types of classes (e.g. controllers).

Upvotes: 7

Related Questions