Search code examples
grailsgrails-ormspock

Grails 4: How to Disable Deep Validation of Domain Objects for Testing


I'm migrating a Grails 2.4.4. application; and some of my Service methods, which perform domain object validation, are failing their test because the validation is cascading to associations. For example,

Test Method

class AdditionalPhotoServiceSpec extends HibernateSpec implements ServiceUnitTest<AdditionalPhotoService>, DataTest {

    Person person
    AdditionalPhotoType additionalPhotoType

    S3Service mockS3Service

    def setup() {
        [Person, AdditionalPhotoType, AdditionalPhoto, Organization].each { mockDomain(it) }
        person = new Person().save(validate: false)
        additionalPhotoType = new AdditionalPhotoType().save(validate: false)

        mockS3Service = Mock()
        service.s3Service = mockS3Service
    }

    def cleanup() {
    }

    def "create additional photo"() {
        when:
        assert person.organization.id
        AdditionalPhoto additionalPhoto = service.create(new AdditionalPhoto(person: person, additionalPhotoType: additionalPhotoType, bytes: [1, 2, 3]))

        then:
        additionalPhoto?.id

        and:
        1 * mockS3Service.storePhoto(testAdditionalPhoto())
    }

This is trying to create an AdditionalPhoto with two associated objects that have been saved with validate: false.

Service Method Under Test

class AdditionalPhotoService {

    S3Service s3Service

    boolean enableDeleteAllForDownloadedPhotos = false

    AdditionalPhoto create(AdditionalPhoto additionalPhoto) {
        additionalPhoto.validate()
        if (additionalPhoto.hasErrors())
            throw new InvalidResourceException(additionalPhoto.errors)

        deletePriorAdditionalPhotos(additionalPhoto)

        additionalPhoto.save()
        additionalPhoto.externalURL = s3Service.storePhoto(additionalPhoto)
        return additionalPhoto
    }
}

Problem

The test fails because additionalPhoto.validate() in the service method is validating the associated objects, Person and AdditionalPhotoType, rather than just the AdditionalPhoto. For production, I like that behavior, but I don't want deep validation for testing because it would require me to create all the domain objects associated with both Person and AdditionalPhotoType and their associations, and their associations, etc. It seems like it would create verbose, fragile test code.

Question

How can I disable deep validation for a domain object just for testing without changing the production code?


Things I've already looked at


Solution

  • Turns out those both those questions had almost what I needed.

    I created the following application.groovy file.

    grails-app/conf/application.groovy

    environments {
        test {
            grails.gorm.default.mapping = {
                '*' cascade:'none'
            }
        }
    }