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

zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 02b9868eea2 Add more test cases on mode module (#37639)
02b9868eea2 is described below

commit 02b9868eea28a4cd1cc7990683eb368bbab4aac9
Author: Liang Zhang <[email protected]>
AuthorDate: Mon Jan 5 00:02:55 2026 +0800

    Add more test cases on mode module (#37639)
---
 .../mode/persist/PersistServiceFacade.java         |   4 +-
 .../mode/persist/PersistServiceFacadeTest.java     |  85 +++++++++
 .../YamlRuleConfigurationReflectionEngineTest.java | 208 +++++++++++++++++++++
 .../datasource/StorageNodeChangedHandlerTest.java  |  69 +++++++
 .../type/GlobalMetaDataChangedListenerTest.java    |  96 ++++++++++
 .../statistics/RefreshStatisticsOperationTest.java |  31 +++
 6 files changed, 491 insertions(+), 2 deletions(-)

diff --git 
a/mode/core/src/main/java/org/apache/shardingsphere/mode/persist/PersistServiceFacade.java
 
b/mode/core/src/main/java/org/apache/shardingsphere/mode/persist/PersistServiceFacade.java
index 3439198353f..41ed3fb3792 100644
--- 
a/mode/core/src/main/java/org/apache/shardingsphere/mode/persist/PersistServiceFacade.java
+++ 
b/mode/core/src/main/java/org/apache/shardingsphere/mode/persist/PersistServiceFacade.java
@@ -47,8 +47,8 @@ public final class PersistServiceFacade implements 
AutoCloseable {
     
     public PersistServiceFacade(final PersistRepository repository, final 
ModeConfiguration modeConfig, final MetaDataContextManager 
metaDataContextManager) {
         this.repository = repository;
-        metaDataFacade = new MetaDataPersistFacade(repository, 
metaDataContextManager.getMetaDataContexts().getMetaData()
-                
.getProps().getValue(ConfigurationPropertyKey.PERSIST_SCHEMAS_TO_REPOSITORY_ENABLED));
+        metaDataFacade = new MetaDataPersistFacade(repository,
+                
metaDataContextManager.getMetaDataContexts().getMetaData().getProps().getValue(ConfigurationPropertyKey.PERSIST_SCHEMAS_TO_REPOSITORY_ENABLED));
         stateService = new StatePersistService(repository);
         qualifiedDataSourceStateService = new 
QualifiedDataSourceStatePersistService(repository);
         modeFacade = 
TypedSPILoader.getService(ModePersistServiceFacadeBuilder.class, 
modeConfig.getType()).build(metaDataContextManager, repository);
diff --git 
a/mode/core/src/test/java/org/apache/shardingsphere/mode/persist/PersistServiceFacadeTest.java
 
b/mode/core/src/test/java/org/apache/shardingsphere/mode/persist/PersistServiceFacadeTest.java
new file mode 100644
index 00000000000..5c3d2afe4f8
--- /dev/null
+++ 
b/mode/core/src/test/java/org/apache/shardingsphere/mode/persist/PersistServiceFacadeTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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
+ *
+ *     http://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.shardingsphere.mode.persist;
+
+import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
+import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.mode.metadata.manager.MetaDataContextManager;
+import org.apache.shardingsphere.mode.persist.mode.ModePersistServiceFacade;
+import 
org.apache.shardingsphere.mode.persist.mode.ModePersistServiceFacadeBuilder;
+import org.apache.shardingsphere.mode.spi.repository.PersistRepository;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class PersistServiceFacadeTest {
+    
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private MetaDataContextManager metaDataContextManager;
+    
+    @Mock
+    private PersistRepository repository;
+    
+    @Mock
+    private ModePersistServiceFacadeBuilder builder;
+    
+    @Mock
+    private ModePersistServiceFacade modeFacade;
+    
+    @Test
+    void assertCreateFacade() {
+        try (MockedStatic<TypedSPILoader> mockedStatic = 
mockStatic(TypedSPILoader.class)) {
+            PersistServiceFacade actual = createFacade(mockedStatic);
+            assertThat(actual.getRepository(), is(repository));
+            assertNotNull(actual.getMetaDataFacade());
+            assertNotNull(actual.getStateService());
+            assertNotNull(actual.getQualifiedDataSourceStateService());
+            assertThat(actual.getModeFacade(), is(modeFacade));
+            verify(builder).build(metaDataContextManager, repository);
+        }
+    }
+    
+    @Test
+    void assertCloseChain() {
+        try (MockedStatic<TypedSPILoader> mockedStatic = 
mockStatic(TypedSPILoader.class)) {
+            PersistServiceFacade actual = createFacade(mockedStatic);
+            actual.close();
+            verify(modeFacade).close();
+            verify(repository).close();
+        }
+    }
+    
+    private PersistServiceFacade createFacade(final 
MockedStatic<TypedSPILoader> mockedStatic) {
+        
when(metaDataContextManager.getMetaDataContexts().getMetaData().getProps().getValue(ConfigurationPropertyKey.PERSIST_SCHEMAS_TO_REPOSITORY_ENABLED)).thenReturn(Boolean.TRUE);
+        mockedStatic.when(() -> 
TypedSPILoader.getService(ModePersistServiceFacadeBuilder.class, 
"FIXTURE")).thenReturn(builder);
+        when(builder.build(metaDataContextManager, 
repository)).thenReturn(modeFacade);
+        return new PersistServiceFacade(repository, new 
ModeConfiguration("FIXTURE", null), metaDataContextManager);
+    }
+}
diff --git 
a/mode/node/src/test/java/org/apache/shardingsphere/mode/node/rule/tuple/YamlRuleConfigurationReflectionEngineTest.java
 
b/mode/node/src/test/java/org/apache/shardingsphere/mode/node/rule/tuple/YamlRuleConfigurationReflectionEngineTest.java
new file mode 100644
index 00000000000..5180d1c0e0f
--- /dev/null
+++ 
b/mode/node/src/test/java/org/apache/shardingsphere/mode/node/rule/tuple/YamlRuleConfigurationReflectionEngineTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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
+ *
+ *     http://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.shardingsphere.mode.node.rule.tuple;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
+import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
+import 
org.apache.shardingsphere.infra.yaml.config.pojo.rule.YamlRuleConfiguration;
+import 
org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper;
+import 
org.apache.shardingsphere.mode.node.rule.tuple.annotation.RuleNodeTupleEntity;
+import 
org.apache.shardingsphere.mode.node.rule.tuple.annotation.RuleNodeTupleField;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
+class YamlRuleConfigurationReflectionEngineTest {
+    
+    @Test
+    void assertFindClassReturnMatchedClass() {
+        try (MockedStatic<ShardingSphereServiceLoader> ignored = 
mockStatic(ShardingSphereServiceLoader.class)) {
+            
when(ShardingSphereServiceLoader.getServiceInstances(YamlRuleConfigurationSwapper.class)).thenReturn(Collections.singleton(new
 FixtureYamlRuleConfigurationSwapper()));
+            
assertThat(YamlRuleConfigurationReflectionEngine.findClass("fixture_rule"), 
is(FixtureYamlRuleConfiguration.class));
+        }
+    }
+    
+    @Test
+    void assertFindClassWhenNotFound() {
+        try (MockedStatic<ShardingSphereServiceLoader> ignored = 
mockStatic(ShardingSphereServiceLoader.class)) {
+            
when(ShardingSphereServiceLoader.getServiceInstances(YamlRuleConfigurationSwapper.class)).thenReturn(Collections.singleton(new
 AnotherYamlRuleConfigurationSwapper()));
+            assertThrows(IllegalArgumentException.class, () -> 
YamlRuleConfigurationReflectionEngine.findClass("missing_rule"));
+        }
+    }
+    
+    @Test
+    void assertFindClassWhenAnnotationMissing() {
+        try (MockedStatic<ShardingSphereServiceLoader> ignored = 
mockStatic(ShardingSphereServiceLoader.class)) {
+            
when(ShardingSphereServiceLoader.getServiceInstances(YamlRuleConfigurationSwapper.class)).thenReturn(Collections.singleton(new
 NoAnnotationYamlRuleConfigurationSwapper()));
+            assertThrows(IllegalArgumentException.class, () -> 
YamlRuleConfigurationReflectionEngine.findClass("no_annotation_rule"));
+        }
+    }
+    
+    @Test
+    void assertGetFieldsOrderedByType() {
+        Collection<Field> actual = 
YamlRuleConfigurationReflectionEngine.getFields(FixtureYamlRuleConfiguration.class);
+        assertThat(actual, hasSize(2));
+        Iterator<Field> iterator = actual.iterator();
+        assertThat(iterator.next().getName(), is("algorithmName"));
+        assertThat(iterator.next().getName(), is("strategyName"));
+    }
+    
+    @Test
+    void assertGetRuleNodeItemName() throws NoSuchFieldException {
+        Field field = 
FixtureYamlRuleConfiguration.class.getDeclaredField("defaultAlgorithmName");
+        
assertThat(YamlRuleConfigurationReflectionEngine.getRuleNodeItemName(field), 
is("default_algorithm_name"));
+    }
+    
+    @RuleNodeTupleEntity("fixture_rule")
+    @Getter
+    @Setter
+    private static final class FixtureYamlRuleConfiguration implements 
YamlRuleConfiguration {
+        
+        @RuleNodeTupleField(type = RuleNodeTupleField.Type.STRATEGY)
+        private String strategyName;
+        
+        @RuleNodeTupleField(type = RuleNodeTupleField.Type.ALGORITHM)
+        private String algorithmName;
+        
+        private String ignoredField;
+        
+        private String defaultAlgorithmName;
+        
+        @Override
+        public Class<? extends RuleConfiguration> getRuleConfigurationType() {
+            return FixtureRuleConfiguration.class;
+        }
+    }
+    
+    private static final class FixtureRuleConfiguration implements 
RuleConfiguration {
+    }
+    
+    private static final class FixtureYamlRuleConfigurationSwapper implements 
YamlRuleConfigurationSwapper<FixtureYamlRuleConfiguration, 
FixtureRuleConfiguration> {
+        
+        @Override
+        public FixtureYamlRuleConfiguration swapToYamlConfiguration(final 
FixtureRuleConfiguration data) {
+            return new FixtureYamlRuleConfiguration();
+        }
+        
+        @Override
+        public FixtureRuleConfiguration swapToObject(final 
FixtureYamlRuleConfiguration yamlConfig) {
+            return new FixtureRuleConfiguration();
+        }
+        
+        @Override
+        public String getRuleTagName() {
+            return "FIXTURE";
+        }
+        
+        @Override
+        public int getOrder() {
+            return 0;
+        }
+        
+        @Override
+        public Class<FixtureRuleConfiguration> getTypeClass() {
+            return FixtureRuleConfiguration.class;
+        }
+    }
+    
+    private static final class NoAnnotationYamlRuleConfiguration implements 
YamlRuleConfiguration {
+        
+        @Override
+        public Class<? extends RuleConfiguration> getRuleConfigurationType() {
+            return FixtureRuleConfiguration.class;
+        }
+    }
+    
+    private static final class NoAnnotationYamlRuleConfigurationSwapper 
implements YamlRuleConfigurationSwapper<NoAnnotationYamlRuleConfiguration, 
FixtureRuleConfiguration> {
+        
+        @Override
+        public NoAnnotationYamlRuleConfiguration swapToYamlConfiguration(final 
FixtureRuleConfiguration data) {
+            return new NoAnnotationYamlRuleConfiguration();
+        }
+        
+        @Override
+        public FixtureRuleConfiguration swapToObject(final 
NoAnnotationYamlRuleConfiguration yamlConfig) {
+            return new FixtureRuleConfiguration();
+        }
+        
+        @Override
+        public String getRuleTagName() {
+            return "NO_ANNOTATION";
+        }
+        
+        @Override
+        public int getOrder() {
+            return 2;
+        }
+        
+        @Override
+        public Class<FixtureRuleConfiguration> getTypeClass() {
+            return FixtureRuleConfiguration.class;
+        }
+    }
+    
+    @RuleNodeTupleEntity("another_rule")
+    private static final class AnotherYamlRuleConfiguration implements 
YamlRuleConfiguration {
+        
+        @Override
+        public Class<? extends RuleConfiguration> getRuleConfigurationType() {
+            return FixtureRuleConfiguration.class;
+        }
+    }
+    
+    private static final class AnotherYamlRuleConfigurationSwapper implements 
YamlRuleConfigurationSwapper<AnotherYamlRuleConfiguration, 
FixtureRuleConfiguration> {
+        
+        @Override
+        public AnotherYamlRuleConfiguration swapToYamlConfiguration(final 
FixtureRuleConfiguration data) {
+            return new AnotherYamlRuleConfiguration();
+        }
+        
+        @Override
+        public FixtureRuleConfiguration swapToObject(final 
AnotherYamlRuleConfiguration yamlConfig) {
+            return new FixtureRuleConfiguration();
+        }
+        
+        @Override
+        public String getRuleTagName() {
+            return "ANOTHER";
+        }
+        
+        @Override
+        public int getOrder() {
+            return 1;
+        }
+        
+        @Override
+        public Class<FixtureRuleConfiguration> getTypeClass() {
+            return FixtureRuleConfiguration.class;
+        }
+    }
+}
diff --git 
a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/database/datasource/StorageNodeChangedHandlerTest.java
 
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/database/datasource/StorageNodeChangedHandlerTest.java
new file mode 100644
index 00000000000..e9b0f3d21e4
--- /dev/null
+++ 
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/handler/database/datasource/StorageNodeChangedHandlerTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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
+ *
+ *     http://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.shardingsphere.mode.manager.cluster.dispatch.handler.database.datasource;
+
+import org.apache.shardingsphere.mode.event.DataChangedEvent;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+import org.apache.shardingsphere.mode.node.path.NodePath;
+import 
org.apache.shardingsphere.mode.node.path.engine.generator.NodePathGenerator;
+import 
org.apache.shardingsphere.mode.node.path.type.database.metadata.datasource.StorageNodeNodePath;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+@ExtendWith(MockitoExtension.class)
+class StorageNodeChangedHandlerTest {
+    
+    @Mock
+    private ContextManager contextManager;
+    
+    @Test
+    void assertGetSubscribedNodePath() {
+        NodePath actual = new 
StorageNodeChangedHandler(contextManager).getSubscribedNodePath("foo_db");
+        assertThat(NodePathGenerator.toPath(actual), 
is("/metadata/foo_db/data_sources/nodes/([\\w-]+)"));
+    }
+    
+    @Test
+    void assertHandleAdded() {
+        DataChangedEvent event = new 
DataChangedEvent(NodePathGenerator.toPath(new StorageNodeNodePath("foo_db", 
"foo_node")), "", DataChangedEvent.Type.ADDED);
+        assertDoesNotThrow(() -> new 
StorageNodeChangedHandler(contextManager).handle("foo_db", event));
+    }
+    
+    @Test
+    void assertHandleUpdated() {
+        DataChangedEvent event = new 
DataChangedEvent(NodePathGenerator.toPath(new StorageNodeNodePath("foo_db", 
"foo_node")), "", DataChangedEvent.Type.UPDATED);
+        assertDoesNotThrow(() -> new 
StorageNodeChangedHandler(contextManager).handle("foo_db", event));
+    }
+    
+    @Test
+    void assertHandleDeleted() {
+        DataChangedEvent event = new 
DataChangedEvent(NodePathGenerator.toPath(new StorageNodeNodePath("foo_db", 
"foo_node")), "", DataChangedEvent.Type.DELETED);
+        assertDoesNotThrow(() -> new 
StorageNodeChangedHandler(contextManager).handle("foo_db", event));
+    }
+    
+    @Test
+    void assertHandleIgnoredType() {
+        DataChangedEvent event = new 
DataChangedEvent(NodePathGenerator.toPath(new StorageNodeNodePath("foo_db", 
"foo_node")), "", DataChangedEvent.Type.IGNORED);
+        assertDoesNotThrow(() -> new 
StorageNodeChangedHandler(contextManager).handle("foo_db", event));
+    }
+}
diff --git 
a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/listener/type/GlobalMetaDataChangedListenerTest.java
 
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/listener/type/GlobalMetaDataChangedListenerTest.java
new file mode 100644
index 00000000000..55f4e28ba41
--- /dev/null
+++ 
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/dispatch/listener/type/GlobalMetaDataChangedListenerTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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
+ *
+ *     http://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.shardingsphere.mode.manager.cluster.dispatch.listener.type;
+
+import 
org.apache.shardingsphere.infra.spi.type.ordered.cache.OrderedServicesCache;
+import org.apache.shardingsphere.mode.event.DataChangedEvent;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+import 
org.apache.shardingsphere.mode.manager.cluster.dispatch.handler.global.GlobalDataChangedEventHandler;
+import 
org.apache.shardingsphere.mode.manager.cluster.dispatch.handler.global.config.GlobalConfigurationChangedHandler;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class GlobalMetaDataChangedListenerTest {
+    
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private ContextManager contextManager;
+    
+    @AfterEach
+    void cleanCache() {
+        OrderedServicesCache.clearCache();
+    }
+    
+    @Test
+    void assertOnChangeWhenTypeNotSubscribed() {
+        
OrderedServicesCache.cacheServices(GlobalDataChangedEventHandler.class, 
Collections.singletonList("type"), Collections.singletonMap("key", "value"));
+        GlobalDataChangedEventHandler handler = 
mock(GlobalDataChangedEventHandler.class);
+        
when(handler.getSubscribedTypes()).thenReturn(Collections.singleton(DataChangedEvent.Type.ADDED));
+        new GlobalMetaDataChangedListener(contextManager, 
handler).onChange(new DataChangedEvent("version_path", "1", 
DataChangedEvent.Type.UPDATED));
+        
assertTrue(OrderedServicesCache.findCachedServices(GlobalDataChangedEventHandler.class,
 Collections.singletonList("type")).isPresent());
+        verify(handler, never()).handle(any(), any());
+    }
+    
+    @Test
+    void assertOnChangeWhenActiveVersionNotMatched() {
+        
OrderedServicesCache.cacheServices(GlobalDataChangedEventHandler.class, 
Collections.singletonList("type"), Collections.singletonMap("key", "value"));
+        
when(contextManager.getPersistServiceFacade().getRepository().query("version_path")).thenReturn("2");
+        GlobalConfigurationChangedHandler handler = 
mock(GlobalConfigurationChangedHandler.class);
+        
when(handler.getSubscribedTypes()).thenReturn(Collections.singleton(DataChangedEvent.Type.UPDATED));
+        new GlobalMetaDataChangedListener(contextManager, 
handler).onChange(new DataChangedEvent("version_path", "1", 
DataChangedEvent.Type.UPDATED));
+        
assertTrue(OrderedServicesCache.findCachedServices(GlobalDataChangedEventHandler.class,
 Collections.singletonList("type")).isPresent());
+        verify(handler, never()).handle(any(), any());
+    }
+    
+    @Test
+    void assertOnChangeWithMatchedActiveVersion() {
+        
OrderedServicesCache.cacheServices(GlobalDataChangedEventHandler.class, 
Collections.singletonList("type"), Collections.singletonMap("key", "value"));
+        
when(contextManager.getPersistServiceFacade().getRepository().query("version_path")).thenReturn("1");
+        GlobalConfigurationChangedHandler handler = 
mock(GlobalConfigurationChangedHandler.class);
+        
when(handler.getSubscribedTypes()).thenReturn(Collections.singleton(DataChangedEvent.Type.UPDATED));
+        DataChangedEvent event = new DataChangedEvent("version_path", "1", 
DataChangedEvent.Type.UPDATED);
+        new GlobalMetaDataChangedListener(contextManager, 
handler).onChange(event);
+        
assertFalse(OrderedServicesCache.findCachedServices(GlobalDataChangedEventHandler.class,
 Collections.singletonList("type")).isPresent());
+        verify(handler).handle(contextManager, event);
+    }
+    
+    @Test
+    void assertOnChangeWithNonConfigurationHandler() {
+        
OrderedServicesCache.cacheServices(GlobalDataChangedEventHandler.class, 
Collections.singletonList("type"), Collections.singletonMap("key", "value"));
+        GlobalDataChangedEventHandler handler = 
mock(GlobalDataChangedEventHandler.class);
+        
when(handler.getSubscribedTypes()).thenReturn(Collections.singleton(DataChangedEvent.Type.UPDATED));
+        DataChangedEvent event = new DataChangedEvent("version_path", "1", 
DataChangedEvent.Type.UPDATED);
+        new GlobalMetaDataChangedListener(contextManager, 
handler).onChange(event);
+        
assertFalse(OrderedServicesCache.findCachedServices(GlobalDataChangedEventHandler.class,
 Collections.singletonList("type")).isPresent());
+        verify(handler).handle(contextManager, event);
+    }
+}
diff --git 
a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/statistics/RefreshStatisticsOperationTest.java
 
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/statistics/RefreshStatisticsOperationTest.java
new file mode 100644
index 00000000000..08802d0be60
--- /dev/null
+++ 
b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/statistics/RefreshStatisticsOperationTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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
+ *
+ *     http://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.shardingsphere.mode.manager.cluster.statistics;
+
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class RefreshStatisticsOperationTest {
+    
+    @Test
+    void assertGetName() {
+        assertThat(new RefreshStatisticsOperation().getName(), 
is("refresh_statistics"));
+    }
+}

Reply via email to