This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch chore/clean-grails-datamapping-async
in repository https://gitbox.apache.org/repos/asf/grails-core.git


The following commit(s) were added to 
refs/heads/chore/clean-grails-datamapping-async by this push:
     new 3e29c85c47 Add test coverage for AsyncEntity.getAsync()
3e29c85c47 is described below

commit 3e29c85c471679934aa851bec5f44f726b6be5a8
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Fri Aug 21 20:51:33 2026 -0500

    Add test coverage for AsyncEntity.getAsync()
    
    The trait's static getAsync() had no direct test and is excluded from
    JaCoCo (its @Generated annotation skips instrumentation), so nothing
    flagged it as untested. Verify it wraps the entity's own registered
    GormStaticApi in a GormAsyncStaticApi and that task() runs through
    that API's session, not some other entity's.
---
 .../grails/gorm/async/AsyncEntitySpec.groovy       | 124 +++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git 
a/grails-datamapping-async/src/test/groovy/grails/gorm/async/AsyncEntitySpec.groovy
 
b/grails-datamapping-async/src/test/groovy/grails/gorm/async/AsyncEntitySpec.groovy
new file mode 100644
index 0000000000..e2360b1726
--- /dev/null
+++ 
b/grails-datamapping-async/src/test/groovy/grails/gorm/async/AsyncEntitySpec.groovy
@@ -0,0 +1,124 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.gorm.async
+
+import grails.async.Promises
+import org.grails.async.factory.SynchronousPromiseFactory
+import org.grails.datastore.gorm.GormEnhancer
+import org.grails.datastore.gorm.GormStaticApi
+import org.grails.datastore.gorm.async.GormAsyncStaticApi
+import org.grails.datastore.mapping.config.Entity as MappedEntity
+import org.grails.datastore.mapping.core.Datastore
+import org.grails.datastore.mapping.core.connections.ConnectionSource
+import org.grails.datastore.mapping.model.ClassMapping
+import org.grails.datastore.mapping.model.MappingContext
+import org.grails.datastore.mapping.model.PersistentEntity
+import spock.lang.Specification
+
+class AsyncEntitySpec extends Specification {
+
+    private def originalPromiseFactory
+
+    void setup() {
+        originalPromiseFactory = Promises.promiseFactory
+        Promises.promiseFactory = new SynchronousPromiseFactory()
+    }
+
+    void cleanup() {
+        Promises.promiseFactory = originalPromiseFactory
+    }
+
+    void "getAsync wraps the entity's own registered static API in a 
GormAsyncStaticApi"() {
+        given: "the entity's static API is registered with GORM"
+        GormStaticApi staticApi = stubStaticApi()
+        registerStaticApi(AsyncEntityFixture, staticApi)
+
+        when:
+        def asyncApi = AsyncEntityFixture.async
+
+        then:
+        asyncApi instanceof GormAsyncStaticApi
+        asyncApi.staticApi.is(staticApi)
+    }
+
+    void "getAsync's task runs the closure inside a new session opened by the 
entity's own static API"() {
+        given: "the entity's static API is registered with GORM"
+        boolean ranInsideNewSession = false
+        GormStaticApi staticApi = stubStaticApi()
+        staticApi.withNewSession(_) >> { Closure c -> ranInsideNewSession = 
true; c.call() }
+        registerStaticApi(AsyncEntityFixture, staticApi)
+
+        when:
+        def result = AsyncEntityFixture.async.task { "done" }.get()
+
+        then:
+        result == "done"
+        ranInsideNewSession
+    }
+
+    private GormStaticApi stubStaticApi() {
+        Mock(GormStaticApi) {
+            getGormPersistentEntity() >> Stub(PersistentEntity) {
+                getJavaClass() >> AsyncEntityFixture
+            }
+        }
+    }
+
+    /**
+     * Registers the given static API as the GORM static API for {@code cls},
+     * mirroring how a real {@code GormEnhancer} bootstraps GORM entities.
+     */
+    private void registerStaticApi(Class cls, GormStaticApi staticApi) {
+        def mappedForm = new MappedEntity()
+        mappedForm.datasources = [ConnectionSource.DEFAULT]
+        def classMapping = Stub(ClassMapping) {
+            getMappedForm() >> mappedForm
+        }
+        def entity = Stub(PersistentEntity) {
+            getJavaClass() >> cls
+            getName() >> cls.name
+            getMapping() >> classMapping
+        }
+        def mappingContext = Stub(MappingContext) {
+            getPersistentEntities() >> []
+        }
+        def datastore = Stub(Datastore) {
+            getMappingContext() >> mappingContext
+        }
+        new StubbingGormEnhancer(datastore, staticApi).registerEntity(entity)
+    }
+
+    private static class StubbingGormEnhancer extends GormEnhancer {
+
+        private final GormStaticApi staticApiToReturn
+
+        StubbingGormEnhancer(Datastore datastore, GormStaticApi 
staticApiToReturn) {
+            super(datastore)
+            this.staticApiToReturn = staticApiToReturn
+        }
+
+        @Override
+        protected <D> GormStaticApi<D> getStaticApi(Class<D> cls, String 
qualifier) {
+            (GormStaticApi<D>) staticApiToReturn
+        }
+    }
+}
+
+class AsyncEntityFixture implements AsyncEntity<AsyncEntityFixture> {
+}

Reply via email to