All Downloads are FREE. Search and download functionalities are using the official Maven repository.

grails.testing.gorm.DataTest.groovy Maven / Gradle / Ivy

There is a newer version: 2023.1.0-M1
Show newest version
/*
 * Copyright 2016-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package grails.testing.gorm

import java.beans.Introspector

import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import groovy.transform.TypeCheckingMode
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.validation.Validator

import grails.core.GrailsClass
import grails.gorm.validation.PersistentEntityValidator

import org.grails.core.artefact.DomainClassArtefactHandler
import org.grails.datastore.gorm.GormEnhancer
import org.grails.datastore.mapping.config.Settings
import org.grails.datastore.mapping.core.AbstractDatastore
import org.grails.datastore.mapping.core.Session
import org.grails.datastore.mapping.model.PersistentEntity
import org.grails.datastore.mapping.model.lifecycle.Initializable
import org.grails.datastore.mapping.services.Service
import org.grails.testing.GrailsUnitTest
import org.grails.testing.gorm.MockCascadingDomainClassValidator
import org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor
import org.grails.validation.ConstraintEvalUtils

@CompileStatic
trait DataTest extends GrailsUnitTest {

    boolean domainsHaveBeenMocked = false
    Session currentSession

    Class[] getDomainClassesToMock() {
        [] as Class[]
    }

    boolean getFailOnError() {
        config.getProperty(Settings.SETTING_FAIL_ON_ERROR, Boolean, false)
    }

    /**
     * Mocks a domain class providing the equivalent GORM behavior but against an in-memory
     * concurrent hash map instead of a database
     *
     * @param domainClassToMock The domain class to mock
     * @param domains Optional. The list of domains to save
     */
    void mockDomain(Class domainClassToMock, List domains = []) {
        mockDomains(domainClassToMock)
        PersistentEntity entity = datastore.mappingContext.getPersistentEntity(domainClassToMock.name)
        if (domains) {
            saveDomainList(entity, domains)
        }
    }

    /**
     * Mocks domain classes providing the equivalent GORM behavior but against an in-memory
     * concurrent hash map instead of a database
     *
     * @param domainClassesToMock The list of domain classes to mock
     */
    void mockDomains(Class... domainClassesToMock) {
        initialMockDomainSetup()
        Collection entities = datastore.mappingContext.addPersistentEntities(domainClassesToMock)
        for (PersistentEntity entity in entities) {
            registerGrailsDomainClass(entity.javaClass)

            Validator validator = registerDomainClassValidator(entity)
            datastore.mappingContext.addEntityValidator(entity, validator)
        }
        new GormEnhancer(datastore, transactionManager, getFailOnError())

        initializeMappingContext()
    }

    /**
     * Called by the ServiceUnitTest class (via reflection) to create a data service
     *
     * @param serviceClass The data service abstract class or interface
     */
    void mockDataService(Class serviceClass) {
        Service service = (Service) datastore.getService(serviceClass)
        String serviceName = Introspector.decapitalize(serviceClass.simpleName)
        if (!applicationContext.containsBean(serviceName)) {
            applicationContext.beanFactory.autowireBean(service)
            service.setDatastore(datastore)
            applicationContext.beanFactory.registerSingleton(serviceName, service)
        }
    }

    /**
     * @deprecated as of v2.1.0 because of of consistency in the method name with
     * other GORM projects. It is recommended to use {@link #getDatastore()} instead.
     *
     * @return The{@link AbstractDatastore}
     */
    @Deprecated
    AbstractDatastore getDataStore() {
        getDatastore()
    }

    AbstractDatastore getDatastore() {
        applicationContext.getBean(AbstractDatastore)
    }

    PlatformTransactionManager getTransactionManager() {
        applicationContext.getBean('transactionManager', PlatformTransactionManager)
    }

    private void registerGrailsDomainClass(Class domainClassToMock) {
        grailsApplication.addArtefact(DomainClassArtefactHandler.TYPE, domainClassToMock)
    }

    @CompileDynamic
    private Validator registerDomainClassValidator(PersistentEntity domain) {
        String validationBeanName = "${domain.javaClass.name}Validator"
        defineBeans {
            "${domain.javaClass.name}"(domain.javaClass) { bean ->
                bean.singleton = false
                bean.autowire = 'byName'
            }

            if (DataTestSetupSpecInterceptor.isOldSetup) {
                GrailsClass grailsDomain = grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, domain.javaClass.name)

                "$validationBeanName"(MockCascadingDomainClassValidator) { bean ->
                    getDelegate().messageSource = ref('messageSource')
                    bean.lazyInit = true
                    getDelegate().domainClass = grailsDomain
                    getDelegate().grailsApplication = grailsApplication
                }
            }
            else {
                "$validationBeanName"(PersistentEntityValidator, domain, ref('messageSource'), ref(DataTestSetupSpecInterceptor.BEAN_NAME))
            }
        }

        applicationContext.getBean(validationBeanName, Validator)
    }

    private void initialMockDomainSetup() {
        ConstraintEvalUtils.clearDefaultConstraints()
        ((DomainClassArtefactHandler) grailsApplication.getArtefactHandler(DomainClassArtefactHandler.TYPE)).setGrailsApplication(grailsApplication)
    }

    private void initializeMappingContext() {
        def context = datastore.mappingContext
        if (context instanceof Initializable) {
            context.initialize()
        }
    }

    @CompileStatic(TypeCheckingMode.SKIP)
    private void saveDomainList(PersistentEntity entity, List domains) {
        for (obj in domains) {
            if (obj instanceof Map) {
                entity.javaClass.newInstance(obj).save()
            }
            else if (entity.isInstance(obj)) {
                obj.save()
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy