You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by ma...@apache.org on 2026/05/06 08:06:57 UTC

(grails-core) 01/01: fix: close mongo connections between tests

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

matrei pushed a commit to branch close-mongo-between-tests
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 0a8671942218ef453c3df64c7c176baa4e8a1121
Author: Mattias Reichel <ma...@gmail.com>
AuthorDate: Wed Apr 8 15:46:38 2026 +0200

    fix: close mongo connections between tests
---
 .../mongo/core/GrailsDataMongoTckManager.groovy    |  56 +++++++-----
 .../core/GrailsDataMongoTckManagerSpec.groovy      | 100 +++++++++++++++++++++
 2 files changed, 136 insertions(+), 20 deletions(-)

diff --git a/grails-data-mongodb/core/src/test/groovy/org/apache/grails/data/mongo/core/GrailsDataMongoTckManager.groovy b/grails-data-mongodb/core/src/test/groovy/org/apache/grails/data/mongo/core/GrailsDataMongoTckManager.groovy
index 022637f6c0..dbf832a927 100644
--- a/grails-data-mongodb/core/src/test/groovy/org/apache/grails/data/mongo/core/GrailsDataMongoTckManager.groovy
+++ b/grails-data-mongodb/core/src/test/groovy/org/apache/grails/data/mongo/core/GrailsDataMongoTckManager.groovy
@@ -18,38 +18,40 @@
  */
 package org.apache.grails.data.mongo.core
 
+import groovy.util.logging.Slf4j
+
 import com.mongodb.BasicDBObject
 import com.mongodb.client.MongoClient
+import org.bson.Document
+import org.slf4j.LoggerFactory
+import org.testcontainers.containers.MongoDBContainer
+import org.testcontainers.containers.output.Slf4jLogConsumer
+
+import org.springframework.context.support.GenericApplicationContext
+import org.springframework.context.support.StaticMessageSource
+import org.springframework.validation.Validator
+
 import grails.core.DefaultGrailsApplication
 import grails.core.GrailsApplication
 import grails.gorm.validation.PersistentEntityValidator
-import groovy.util.logging.Slf4j
 import org.apache.grails.data.testing.tck.base.GrailsDataTckManager
 import org.apache.grails.testing.mongo.AbstractMongoGrailsExtension
-import org.bson.Document
 import org.grails.datastore.bson.query.BsonQuery
 import org.grails.datastore.gorm.GormEnhancer
 import org.grails.datastore.gorm.mongo.Birthday
 import org.grails.datastore.gorm.validation.constraints.eval.DefaultConstraintEvaluator
 import org.grails.datastore.gorm.validation.constraints.registry.DefaultConstraintRegistry
+import org.grails.datastore.mapping.core.DatastoreUtils
 import org.grails.datastore.mapping.core.Session
-import org.grails.datastore.mapping.multitenancy.MultiTenancySettings
-import org.grails.datastore.mapping.multitenancy.resolvers.SystemPropertyTenantResolver
 import org.grails.datastore.mapping.engine.types.AbstractMappingAwareCustomTypeMarshaller
 import org.grails.datastore.mapping.model.MappingContext
 import org.grails.datastore.mapping.model.PersistentEntity
 import org.grails.datastore.mapping.model.PersistentProperty
-import org.grails.datastore.mapping.mongo.AbstractMongoSession
-import org.grails.datastore.mapping.core.DatastoreUtils
 import org.grails.datastore.mapping.mongo.MongoDatastore
 import org.grails.datastore.mapping.mongo.config.MongoSettings
+import org.grails.datastore.mapping.multitenancy.MultiTenancySettings
+import org.grails.datastore.mapping.multitenancy.resolvers.SystemPropertyTenantResolver
 import org.grails.datastore.mapping.query.Query
-import org.slf4j.LoggerFactory
-import org.springframework.context.support.GenericApplicationContext
-import org.springframework.context.support.StaticMessageSource
-import org.springframework.validation.Validator
-import org.testcontainers.containers.MongoDBContainer
-import org.testcontainers.containers.output.Slf4jLogConsumer
 
 @Slf4j
 class GrailsDataMongoTckManager extends GrailsDataTckManager {
@@ -136,17 +138,31 @@ class GrailsDataMongoTckManager extends GrailsDataTckManager {
 
     @Override
     void destroy() {
-        mongoDatastore.getMongoClient().listDatabaseNames().findAll {!(it in ['admin', 'config', 'local']) }.each {
+        try {
+            mongoDatastore?.mongoClient?.listDatabaseNames()
+                    ?.findAll { !(it in ['admin', 'config', 'local']) }
+                    ?.each {
+                        try {
+                            mongoDatastore.mongoClient.getDatabase(it as String).drop()
+                        }
+                        catch (ignored) {
+                            log.warn("Could not drop ${it}")
+                        }
+                    }
+            for (cls in domainClasses) {
+                GormEnhancer.findValidationApi(cls).validator = null
+            }
+        }
+        finally {
             try {
-                mongoDatastore.getMongoClient().getDatabase(it).drop()
+                mongoDatastore?.close()
             }
-            catch(e) {
-                log.warn("Could not drop ${it}")
+            catch (ignored) {
             }
-        }
-        mongoDatastore.buildIndex()
-        for (cls in getDomainClasses()) {
-            GormEnhancer.findValidationApi(cls).setValidator(null)
+            mongoDatastore = null
+            mongoClient = null
+            grailsApplication = null
+            mappingContext = null
         }
 
         super.destroy()
diff --git a/grails-data-mongodb/core/src/test/groovy/org/apache/grails/data/mongo/core/GrailsDataMongoTckManagerSpec.groovy b/grails-data-mongodb/core/src/test/groovy/org/apache/grails/data/mongo/core/GrailsDataMongoTckManagerSpec.groovy
new file mode 100644
index 0000000000..8dd9adc962
--- /dev/null
+++ b/grails-data-mongodb/core/src/test/groovy/org/apache/grails/data/mongo/core/GrailsDataMongoTckManagerSpec.groovy
@@ -0,0 +1,100 @@
+/*
+ * 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 org.apache.grails.data.mongo.core
+
+import org.apache.grails.data.testing.tck.domains.DataServiceRoutingProduct
+import org.apache.grails.data.testing.tck.domains.DataServiceRoutingProductService
+import org.apache.grails.data.testing.tck.tests.DataServiceConnectionRoutingSpec
+import spock.lang.Specification
+
+class GrailsDataMongoTckManagerSpec extends Specification {
+
+    void 'cleanup closes the primary datastore so repeated setup stays healthy'() {
+        given:
+        def manager = new GrailsDataMongoTckManager()
+        manager.setupSpec()
+
+        when:
+        manager.setup(DataServiceConnectionRoutingSpec)
+        manager.setupMultiDataSource(DataServiceRoutingProduct)
+
+        and:
+        def productService = manager.getServiceForConnection(
+                DataServiceRoutingProductService,
+                'secondary'
+        ) as DataServiceRoutingProductService
+        def saved = productService.save(
+                new DataServiceRoutingProduct(name: 'product-0', amount: 1)
+        )
+
+        then:
+        saved != null
+        saved.id != null
+        manager.mongoDatastore != null
+
+        when:
+        manager.cleanupMultiDataSource()
+        manager.cleanup()
+
+        then:
+        manager.mongoDatastore == null
+        manager.mongoClient == null
+        manager.grailsApplication == null
+        manager.mappingContext == null
+
+        when:
+        manager.setup(DataServiceConnectionRoutingSpec)
+        manager.setupMultiDataSource(DataServiceRoutingProduct)
+
+        and:
+        productService = manager.getServiceForConnection(
+                DataServiceRoutingProductService,
+                'secondary'
+        ) as DataServiceRoutingProductService
+        saved = productService.save(
+                new DataServiceRoutingProduct(name: 'product-1', amount: 1)
+        )
+
+        then:
+        saved != null
+        saved.id != null
+        manager.mongoDatastore != null
+
+        when:
+        manager.cleanupMultiDataSource()
+        manager.cleanup()
+
+        then:
+        manager.mongoDatastore == null
+        manager.mongoClient == null
+        manager.grailsApplication == null
+        manager.mappingContext == null
+
+        then:
+        noExceptionThrown()
+
+        cleanup:
+        manager.cleanupMultiDataSource()
+        manager.cleanup()
+        manager.cleanupSpec()
+    }
+}
+
+
+